tableview的reloadData应注意dataSourc

2017-03-14  本文已影响614人  怕腥的鱼

UITableView reloadData的正确方法。
相信很多人会遇到这种情况,当tableView正在滚动的时候,如果reloadData,偶尔发生App crash的情况。

在tableView的dataSource被改变 和 tableView的reloadData被调用之间有个时间差,而正是在这个期间,tableView的delegate方法被调用,如果新的dataSource的count小于原来的dataSource count,crash就很有可能发生了。

下面的笔记提供了两种解决方案,和记录了一个典型的错误,即 在background thread中修改了datasource,虽然调用 [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nilwaitUntilDone:NO];

记住正确的原则: Always change the dataSource and(注意这个and) reloadData in the mainThread. What's more, reloadData should be called immediately after the dataSource change.
If dataSource is changed but tableView's reloadData method is not called immediately, the tableView may crash if it's in scrolling.
Crash Reason: There is still a time gap between the dataSource change and reloadData. If the table is scrolling during the time gap, the app may Crash!!!!

WRONG WAY:
Following codes is WRONG: even the reloadData is called in main thread, there is still a time gap between the dataSource change and reloadData. If the table is scrolling during the time gap, the app may Crash!!!!
wrong codes samples:

-(void) changeDatasource_backgroundThread
{
@autoreleasepool{
[self.dataSourceArray removeAllObjects]; 
[self.tableViewperformSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
    }
}

RIGHT WAY:
Principle: Always change dataSource in MAIN thread and call the reloadData immediately after it.
Option 1: If the operation to change the dataSource should be executed in background, the operation can create a temp dataSource array and pass it to main thread with notification, the main thread observes the notification, assign the tmpDataSource to dataSource and reload the tableView by reloadData.

Option 2: In the background, call the GDC dispatch_async to send the two methods to main thread together.

dispatch_async(dispatch_get_main_queue(), ^{
        self.dataSourceArray= a new Array.
        [self.tableView reloadData];
});
上一篇下一篇

猜你喜欢

热点阅读