UITableView reloadData的正確方法
轉(zhuǎn)至一個(gè)牛人的貼,自己看了深有收獲霎挟,轉(zhuǎn)載了保存窝剖,也給學(xué)習(xí)開發(fā)IOS的同行參考。
相信很多人會(huì)遇到這種情況酥夭,當(dāng)tableView正在滾動(dòng)的時(shí)候,如果reloadData脊奋,偶爾發(fā)生App crash的情況熬北。 這種情況有時(shí)候有,有時(shí)候沒有诚隙,已經(jīng)難倒了很多人讶隐。直至今天,我在stackoverflow上面久又,仍沒有發(fā)現(xiàn)真正有說到其本質(zhì)的帖子巫延。我的處女貼,選擇這個(gè)問題來闡述一下我的觀點(diǎn)地消。
小弟我英語很好炉峰,一般都是用英語記筆記,當(dāng)然脉执,我知道疼阔,論壇憤青很多,如果只貼英文出來半夷,肯定找罵婆廊。 故簡單翻譯一下,以顯示我的誠意巫橄。 原英文筆記附在后面淘邻。 請大家不要挑英語語法錯(cuò)誤了,筆記就是筆記湘换,不是出書宾舅。
第一句話敬尺,闡述問題的本質(zhì):在tableView的dataSource被改變 和 tableView的reloadData被調(diào)用之間有個(gè)時(shí)間差,而正是在這個(gè)期間贴浙,tableView的delegate方法被調(diào)用砂吞,如果新的dataSource的count小于原來的dataSource count,crash就很有可能發(fā)生了崎溃。
下面的筆記提供了兩種解決方案蜻直,和記錄了一個(gè)典型的錯(cuò)誤,即 在background thread中修改了datasource,雖然調(diào)用[self.tableViewperformSelectorOnMainThread:@selector(reloadData)withObject:nilwaitUntilDone:NO];
記住正確的原則:Always change the dataSourceand(注意這個(gè)and)reloadData in the mainThread. What's more, reloadData should be calledimmediatelyafter 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.dataSourceArrayremoveAllObjects];
[self.tableViewperformSelectorOnMainThread:@selector(reloadData)withObject:nilwaitUntilDone:NO];
}
}
RIGHT WAY:
Principle:Always change dataSource inMAINthread and call the reloadDataimmediatelyafter 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 threadtogether.
dispatch_async(dispatch_get_main_queue(), ^{
self.dataSourceArray= a new Array.
[self.tableView reloadData];
});
轉(zhuǎn)至: