Swift 闭包 [weak self] 和异步任务

12

假设您想要从服务器异步加载一些文本,并在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]的开源应用程序之后,我不确定了。

例如:

只有在会创建强引用循环的情况下才真正需要使用[unowned self]或[weak self]。 (Swift中我们是否总是要在闭包中使用[unowned self])

在我的情况下不存在强引用循环。

或者:

但是要明确的是,在这种情况下最好仍然使用强引用。 (Swift ARC和块)

B.) 假设使用强引用没有问题。当用户在异步加载过程中导航到不同的页面时,ViewController会发生什么?它会保留不可见的ViewController直到异步任务完成而使其占用应用程序内存吗?

1个回答

16

这里没有强引用循环(保留循环)。如果您对 self 使用强引用,它会在调度块运行时立即解决。理论上,如果需要,您可以在此处使用强引用。

话虽如此,在这种情况下,我建议使用弱引用。仅为更新已经被关闭的视图的文本字段而维护强引用并不值得。如果您正在更新其他模型对象或类似内容,则可能需要保持强引用,但在这种情况下不需要这样做。作为一般原则,应尽快释放内存。

更好的方法是,我也会观察 "长时间异步操作" 并决定在视图控制器被关闭后是否真的想让它继续运行。如果不想让它继续运行,我倾向于使请求可取消,然后在 deinit 中取消请求。在这种情况下,您肯定需要使用弱引用(否则 deinit 将一直等到长时间异步操作完成才被调用)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接