user250818
user250818

Reputation:

iOS view controller lifecycle when using background threads

I am unclear on how to handle the following scenario...

Assume that you have a ViewController that needs to perform a long running operation. The ViewController calls performSelectorInBackground to start the long running operation, which in turn will call performSelectorOnMainThread when it is done. Now, assume that the View gets deallocated during the long running operation, perhaps because the user navigated backward in the UINavigationController. When the background operation completes, it is going to try to send a message to a deallocated object.

What is the best way to handle this? It is in my requirements that the user must be able to abandon the screen during the operation, so preventing the backward navigation is not an option.

Upvotes: 1

Views: 2316

Answers (4)

Lachlan Roche
Lachlan Roche

Reputation: 25946

Have the controller track the visibility of the view in viewWillAppear: and viewWillDisappear:. The background task should only update the view if it is visible.

if (self.viewIsVisible) {
    // update view
}

Upvotes: 0

Idan
Idan

Reputation: 5807

performSelectorInBackground retains the receiver, meaning you won't have any problem of operating on a deallocated object.

Read about it here

Upvotes: 2

Marc W
Marc W

Reputation: 19241

In the method that's being performed in the background, why don't you just retain self at the beginning and release it at the end? That way the view controller won't get deallocated. You could run into the problems, though, if the user navigates back to that view controller again and continues going forward and backward a lot. You'll have tons of threads executing.

Upvotes: 0

drewag
drewag

Reputation: 94703

One way to handle this would be to setup a thread manually instead of just using performSelectorInBackground. You would then start this operation on that thread and if at any point, the view that called this thread is destroyed, you would either kill the thread or send a message to it saying to clean up and stop the current task. Worst case is you could just set a variable that would be checked before sending the message to the view to make sure it is still around (but make sure the variable is thread safe).

Upvotes: 0

Related Questions