Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop execution of a GCD, when the ViewController is popped

I have a -[tableView reloadData] method in my app and to make the execution faster, I have called it in a GCD in the following method.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{

    [tableView reloadData];
});    

But when I pop my viewController, the app crashes with this message [SecondViewController numberOfSectionsInTableView:]: message sent to deallocated instance 0x7fe376206e10. I am assuming that the [reloadData] is still being executed after I exit from that ViewController. How can I stop its execution? Should I make this into an NSOperation? If so, how will I do it?

like image 643
Sidharth J Dev Avatar asked May 07 '15 04:05

Sidharth J Dev


1 Answers

There are a couple of problems with your code. Here are the sequence of events leading up to the crash

1) The block captures the tableView and keeps it alive.

2) Your view controller is then deallocated by the pop,

3) The block executes and the tableView calls through to it's data source (your view controller) which is now deallocated.

You can solve this by stoping either #1 or #3 above. I would suggest #1. (I'm assuming ARC here)

__weak UITableView *weakTableView = tableView;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [weakTableView reloadData];
});

If this doesn't work, something else is likely keeping the tableView alive. You should investigate what exactly is doing that but you can also fix the crash by preventing #3 from your view controllers dealloc method:

- (void)dealloc {
    self.tableView.dataSource = nil;
    self.tableView.delegate = nil;
}
like image 177
Lance Avatar answered Nov 14 '22 23:11

Lance