I have a relatively long running task (5-10 secs) in a view controller in my iOS app. It is running async in the background by GCD. The user has the ability to make UI operations during this task, so he also has the ability to press back button to navigate to the previous view.
My code is pretty straightforward:
dispatch_queue_t queue = dispatch_queue_create("com.x.y.z", NULL);
dispatch_async(queue, ^{
TestObject* test = [self getTestObject];
dispatch_async(dispatch_get_main_queue(), ^{
test.resultset.count > 0 ?
[self performSegueWithIdentifier:@"xy" sender:self] :
[UIUtils showSimpleAlert:NSLocalizedString(@"NoDataForInterval",nil)
delegate:self];
});
});
Exception info: Terminating app due to uncaught exception NSGenericException
, reason:
Could not find a navigation controller for segue 'xy'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.
So, the problem is, when my user goes back to the previous view, the task in GCD continues, and when finishing, it crashes my app, because can not perform my segue.
So, my question: how can I cancel my asny task in GCD when navigating to another view? Or just simply test somehow the current view when completing, like
if(!self.navigationController)
return;
Or...?
Thanks for all!
So did you try that? Once you're back on the main thread, it's perfectly safe and reasonable to look around at the state of the interface.
If, on the other hand, you really want to make it easy to cancel your lengthy task in the middle, use NSOperation instead of GCD blocks. This gives you a thread-safe cancellation API.