Just to be clear about all the answers here–how you should fix this error depends on your needs.
The problem with the code in the original question is that self
, which is a UIViewController
, is being accessed from an asynchronously executed NSOperation
block, and this is being done inside the completion handler of an asynchronous NSURLSessionTask
.
By the time the runtime reaches self.textArea!.text
, self
has become nil
. Under what circumstances will a UIViewController
be deallocated? When you pop it out of the navigation stack, when it is dismissed, etc. I’m guessing that the code for btnSendRequestTapped(:)
above isn’t complete and has a popViewController()
somewhere.
The solutions are:
1: To use weak
instead of unowned
. The difference between the two is that weak
means the captured object (self
) may be nil
and turns it into an optional, while unowned
means that you are certain self
will never be nil
and you can access self
as is. Using weak
means unwrapping self
before using it. If it’s nil, do nothing in the code.
{[weak self] in
if let strongSelf = self {
// ...
strongSelf.textArea!.text = "123"
}
}
2: The other solution is to cancel the NSURLSessionTask
and its completion handler (which is dispatched into an NSOperationQueue
property of NSURLSession
called delegateQueue
) if the UIViewController
is being popped out of the navigation stack.
func btnSendRequestTapped() {
// pop the view controller here...
sessionTask.cancel()
sessionTask.delegateQueue.cancelAllOperations()
}
3: Keep using [unowned self]
, but don’t pop the view controller until the operation block is done. I personally prefer this approach.
In short, keep self
from being deallocated until you’re actually done with it.