我的应用程序中有一个-[tableView reloadData]
方法,为了加快执行速度,我已通过以下方法在GCD中调用它。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[tableView reloadData];
});
但是当我弹出我的viewController时,应用程序崩溃了这条消息[SecondViewController numberOfSectionsInTableView:]: message sent to deallocated instance 0x7fe376206e10
。我假设退出ViewController后[reloadData]
仍在执行。我该如何停止执行?我应该把它变成NSOperation吗?如果是这样,我将如何做?
答案 0 :(得分:3)
您的代码存在一些问题。以下是导致崩溃的事件序列
1)该块捕获tableView并使其保持活动状态。
2)然后你的视图控制器被pop,
取消分配3)块执行,tableView调用它的数据源(你的视图控制器),现在已经解除分配。
你可以通过停止上面的#1或#3来解决这个问题。我建议#1。 (我在这里假设ARC)
__weak UITableView *weakTableView = tableView;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[weakTableView reloadData];
});
如果这不起作用,其他一些东西可能会使tableView保持活跃状态。您应该调查究竟是做什么的,但您也可以通过阻止视图控制器dealloc
方法中的#3来修复崩溃:
- (void)dealloc {
self.tableView.dataSource = nil;
self.tableView.delegate = nil;
}
答案 1 :(得分:0)
作为一个选项,您可以弱保留数据源并检查它:
__weak __typeof__(self) dataSource = self; // or whatever it is
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
if (dataSource!=nil)
{
[weakTable reloadData];
}
});
如果您持有数据源,将新的数据源设置为表视图并再次删除该数据源,则仍然存在非常不可能的崩溃,因此将其解除分配。
答案 2 :(得分:-1)
不幸的是,您无法停止GCD执行,但还有其他方法可以解决此问题。由于本主题中的主要问题是关于停止执行,我将使用NSOperation根据您的要求发布解决方案。
1-创建一个NSOperationQueue
NSOperationQueue *_myQueue;
_myQueue = [NSOperationQueue new];
_myQueue.name = @"com.my.queue";
2-从队列中重新加载您的表。 (我会使用块好吗?)
[_myQueue addOperationWithBlock:^{
//your really expensive function
//and your table reload call
[tableView reloadData];
}];
3-现在您可以使用
取消执行//maybe you will want to do this on viewDidDisappear
[_myQueue cancelAllOperations];
<强>更新强>
哎呀,我看到你正在推迟表重载调用,但是NSOperation没有延迟机制。要解决此问题,您可以使用
模拟延迟[NSThread sleepForTimeInterval:1.5];
在[tableView reloadData];
内调用addOperationWithBlock:
或继续使用GCD,然后更改tableView对weak
的引用,以避免阻止保留tableView对象,像这样:
__weak __typeof__(tableView) weakTable = tableView;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
//Now, if your table object was released at this point, the reloadData
//will be ignored
[weakTable reloadData];
});
希望它有所帮助...