简体   繁体   中英

Capturing self weak or unowned on asynchronous network requests

Whenever I am doing asynchronous network requests it could be that on arrival of the request self is already nil (eg the ViewController is already dismissed).

To prevent this I am usually capturing self as weak:

    future.onSuccess(context: Queue.main.context, callback: { [weak self] result in
        if let strongSelf = self {
            // Do some stuff with self, which is now guaranteed to be not nil
            // strongSelf.someMethod()
        }
    })

Or I could capture self as unowned:

    future.onSuccess(context: Queue.main.context, callback: { [unowned self] result in
            // Do some stuff with self
            // self.someMethod()
    })

I do not care about the request returning, because when the request is returning at a point in time when the ViewController is already dismissed I have nothing to show from the request. So I do not want to keep self "alive" with the closure.

My question is now - is it enough to capture self as unowned in this case? Or do I have to do all the time the nil checking with [weak self]? What happens in case of unowned capturing with the request when it arrives and self is already nil - is the closure also still alive and would execute and would trigger a runtime error on accessing nil? Or would the closure also be deallocated together with self and the request would run into the "void"?

Or can I forget both weak and unowned in this case because when self get's deallocated the closure will also be deallocated and so there is no danger of accessing nil on arrival of the request?

PS: I know that there are already many questions-answers on this topic but I could not find an answer in the case I do not care about the async arrival.

If you capture self without weak or unowned keywords, your view controller will be retained by the closure and will not deallocate before the closure dies. The difference between weak and unowned is that weak is an Optional and requires conditional binding as a safety check. On the other hand, unowned is not as fail-safe. It assumes that your view controller is still alive and it will crash if it is not. For more information see this answer .

You do not want to use unowned in this case, because if the object is deallocated before the call finishes, you have a dangling reference that is not set to nil . If you try to use this reference when the request finishes, the app will crash.

As an aside, if you really don't need the response anymore, you should also cancel the request when the view controller is deallocated. If you use NSURLSession , you always get a NSURLSessionTask reference which can be cancelled. So, one would often combine the use of [weak self] pattern in the closure with code that saves an additional weak reference to the NSURSessionTask and have a deinit conditionally cancel that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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