简体   繁体   English

Swift闭包[弱自我]和异步任务

[英]Swift closures [weak self] and async tasks

Imagine a situation, when you want to asynchronously load some text from the server and display the result in the ViewController's UITextField . 想象一种情况,当你想从服务器异步加载一些文本并在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.) Do I need to use [weak self] within the closure used for async calls? A.)我是否需要在用于异步调用的闭包中使用[weak self]?

I thought I need to, but I am not sure after I read some Q/A here at StackOverflow and went through quite a few open source apps that don't use [weak self] for async tasks + closures. 我认为我需要,但是我不确定在StackOverflow上读了一些Q / A并经历了一些不使用[弱自我]进行异步任务+闭包的开源应用程序。

ie: 即:

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 ) 我们总是在Swift中使用[unowned self]内部封闭

There is no strong reference cycle in my case. 在我的案例中没有强大的参考周期。

or: 要么:

But to be clear, it would still be best to use a strong reference in this circumstance. 但要明确的是,在这种情况下使用强力参考仍然是最好的。 ( Swift ARC and blocks ) Swift ARC和块

B.) Let's say it's good to go with the strong reference. B.)让我们说强有力的参考是好的。 What happens to the ViewController when the user navigates to the different page in the middle of async loading? 当用户在异步加载过程中导航到不同的页面时,ViewController会发生什么? Would it keep the invisible ViewController in the app memory until the async task finishes? 在异步任务完成之前,它是否会将不可见的ViewController保留在应用程序内存中?

There is no strong reference cycle (retain cycle) here. 这里没有强大的参考周期(保留周期)。 If you employ a strong reference to self , it is resolved as soon as the dispatch block runs. 如果您对self使用强引用,则在调度块运行后立即解析。 You theoretically could use strong reference here if you needed to. 如果需要,理论上你可以在这里使用强引用。

Having said that, I would advise using a weak reference in this case. 话虽如此,我建议在这种情况下使用弱引用。 There's no point in maintaining a strong reference for the duration of the time consuming process solely for the purpose of updating a text field for a view that has already been dismissed. 对于耗时过程的持续时间保持强有力的参考是没有意义的,仅仅是为了更新已经被解雇的视图的文本字段。 If you were updating other model objects or the like, perhaps you might need to keep the strong reference, but you don't need to do so in this case. 如果您正在更新其他模型对象等,可能您可能需要保留强引用,但在这种情况下您不需要这样做。 As a general principle, one should release memory as soon as reasonably possible. 作为一般原则,人们应该尽快释放记忆。

Even better, I'd also look at the "long running async operation" and decide whether I really want it to continue to run after the view controller has been dismissed. 更好的是,我还会看一下“长时间运行的异步操作”,并决定是否真的希望它在视图控制器被解除后继续运行。 If not, I'd be inclined to also make the request cancelable and then have deinit cancel the request. 如果没有,我倾向于使请求可取消,然后deinit取消请求。 And, in that case, you would definitely want to use weak reference (or else deinit wouldn't be called until the long running async operation finishes). 并且,在这种情况下,您肯定希望使用弱引用(否则在长时间运行的异步操作完成之前不会调用deinit )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM