想象一种情况,当您想要从服务器异步加载一些文本并将结果显示在ViewController的
UITextField
。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
//... some long running async operation
if let textResponse = responseFromServer {
dispatch_async(dispatch_get_main_queue(), { [weak self] () in
self?.textField.text = textResponse
})
}
})
A.) 我是否需要在用于异步调用的闭包中使用 [weak self]?
我认为我需要这样做,但在我阅读了 StackOverflow 上的一些问答并浏览了很多不使用 [weak self] 进行异步任务 + 闭包的开源应用程序后,我不确定。
即:
The only time where you really want to use [unowned self] or [weak self] is when you would create a strong reference cycle. (Shall we always use [unowned self] inside closure in Swift)
在我的案例中没有强引用循环。
或:
But to be clear, it would still be best to use a strong reference in this circumstance. (Swift ARC and blocks)
B.) 假设使用强引用很好。 当用户在异步加载过程中导航到不同的页面时,ViewController 会发生什么?它会在异步任务完成之前将不可见的 ViewController 保留在应用程序内存中吗?
最佳答案
这里没有强引用循环(retain cycle)。如果您使用对 self
的强引用,它会在调度 block 运行时立即解析。如果需要,理论上您可以在此处使用强引用。
话虽如此,我还是建议在这种情况下使用弱引用。在耗时的过程中,仅仅为了更新已被关闭的 View 的文本字段而维持强引用是没有意义的。如果您正在更新其他模型对象等,也许您可能需要保留强引用,但在这种情况下您不需要这样做。作为一般原则,应尽快释放内存。
更好的是,我还会查看“长时间运行的异步操作”并决定我是否真的希望它在 View Controller 被关闭后继续运行。如果不是,我也倾向于使请求可取消,然后让 deinit
取消请求。并且,在那种情况下,您肯定会希望使用弱引用(否则 deinit
在长时间运行的异步操作完成之前不会被调用)。
关于ios - Swift 闭包 [weak self] 和异步任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30920576/