Swift 闭包 [weak self] 和异步任务
Posted
技术标签:
【中文标题】Swift 闭包 [weak self] 和异步任务【英文标题】:Swift closures [weak self] and async tasks 【发布时间】:2015-09-04 09:35:45 【问题描述】:想象一种情况,当您想要异步从服务器加载一些文本并将结果显示在 ViewController's
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] 吗?
我认为我需要这样做,但在阅读了 *** 上的一些 Q/A 并浏览了很多不使用 [weak self] 进行异步任务 + 闭包的开源应用程序之后,我不确定。
即:
你真正想要使用 [unowned self] 或 [weak self] 是您创建强参考循环的时候。 (Shall we always use [unowned self] inside closure in Swift)
在我的例子中没有强引用循环。
或:
但要明确一点,最好还是使用强引用 这种情况。 (Swift ARC and blocks)
B.) 假设使用强参考很好。 当用户在异步加载过程中导航到不同的页面时,ViewController 会发生什么?它会在异步任务完成之前将不可见的 ViewController 保留在应用内存中吗?
【问题讨论】:
【参考方案1】:这里没有强引用循环(retain cycle)。如果您使用对self
的强引用,则它会在调度块运行后立即解决。如果需要的话,理论上你可以在这里使用强引用。
话虽如此,我建议在这种情况下使用弱引用。在耗时过程的持续时间内保持强引用是没有意义的,仅仅是为了更新已经被关闭的视图的文本字段。如果您正在更新其他模型对象等,也许您可能需要保留强引用,但在这种情况下您不需要这样做。作为一般原则,应该尽快释放内存。
更好的是,我还会查看“长时间运行的异步操作”并决定我是否真的希望它在视图控制器被关闭后继续运行。如果不是,我也倾向于取消请求,然后让deinit
取消请求。而且,在这种情况下,您肯定希望使用弱引用(否则在长时间运行的异步操作完成之前不会调用 deinit
)。
【讨论】:
以上是关于Swift 闭包 [weak self] 和异步任务的主要内容,如果未能解决你的问题,请参考以下文章
在所有成员初始化之前由闭包捕获的 Swift5(+RxSwift) 'self'