UITableView reloadData的正确方法
2016-10-10 11:38
330 查看
转自:http://www.cocoachina.com/bbs/read.php?tid=81462
相信很多人会遇到这种情况,当tableView正在滚动的时候,如果reloadData,偶尔发生App
crash的情况。这种情况有时候有,有时候没有,已经难倒了很多人。直至今天,我在stackoverflow上面,仍没有发现真正有说到其本质的帖子。我的处女贴,选择这个问题来阐述一下我的观点。
小弟我英语很好,一般都是用英语记笔记,当然,我知道,论坛愤青很多,如果只贴英文出来,肯定找骂。 故简单翻译一下,以显示我的诚意。原英文笔记附在后面。请大家不要挑英语语法错误了,笔记就是笔记,不是出书。
第一句话,阐述问题的本质:在tableView的dataSource被改变 和tableView的reloadData被调用之间有个时间差,而正是在这个期间,tableView的delegate方法被调用,如果新的dataSource的count小于原来的dataSourcecount,crash就很有可能发生了。
下面的笔记提供了两种解决方案,和记录了一个典型的错误,即 在background thread中修改了datasource,虽然调用 [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nilwaitUntilDone:NO];
记住正确的原则: Always
change thedataSource and(注意这个and) reloadDatain the mainThread. What's more, reloadData should becalled immediately afterthe
dataSource change.
IfdataSource
is changed but tableView's reloadData method is notcalled immediately, the tableView may crash if it's inscrolling.
CrashReason: There
is still a time gap between thedataSource change and reloadData. If the table is scrolling duringthe time gap, the app may Crash!!!!
WRONGWAY:
Following
codes is WRONG: eventhe reloadData is called in main thread, there is still a time gapbetween the dataSource change and reloadData. If the table isscrolling during the time gap, the app mayCrash!!!!
wrongcodes
samples:
-(void)changeDatasource_backgroundThread
{
@autoreleasepool{
[self.dataSourceArray removeAllObjects];
[self.tableViewperformSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
}
}
RIGHTWAY:
Principle:
Always changedataSource in MAIN threadand call the reloadData immediately afterit.
Option1: If
the operation to change thedataSource should be executed in background, the operation cancreate a temp dataSource array and pass it to main thread withnotification, the main thread observes the notification, assign the tmpDataSource to dataSource and
reloadthe tableView by reloadData.
Option2: In
the background, call the GDCdispatch_async to send the two methods to mainthread together.
dispatch_async(dispatch_get_main_queue(),^{
self.dataSourceArray=a
new Array.
[self.tableView reloadData];
});
相信很多人会遇到这种情况,当tableView正在滚动的时候,如果reloadData,偶尔发生App
crash的情况。这种情况有时候有,有时候没有,已经难倒了很多人。直至今天,我在stackoverflow上面,仍没有发现真正有说到其本质的帖子。我的处女贴,选择这个问题来阐述一下我的观点。
小弟我英语很好,一般都是用英语记笔记,当然,我知道,论坛愤青很多,如果只贴英文出来,肯定找骂。 故简单翻译一下,以显示我的诚意。原英文笔记附在后面。请大家不要挑英语语法错误了,笔记就是笔记,不是出书。
第一句话,阐述问题的本质:在tableView的dataSource被改变 和tableView的reloadData被调用之间有个时间差,而正是在这个期间,tableView的delegate方法被调用,如果新的dataSource的count小于原来的dataSourcecount,crash就很有可能发生了。
下面的笔记提供了两种解决方案,和记录了一个典型的错误,即 在background thread中修改了datasource,虽然调用 [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nilwaitUntilDone:NO];
记住正确的原则: Always
change thedataSource and(注意这个and) reloadDatain the mainThread. What's more, reloadData should becalled immediately afterthe
dataSource change.
IfdataSource
is changed but tableView's reloadData method is notcalled immediately, the tableView may crash if it's inscrolling.
CrashReason: There
is still a time gap between thedataSource change and reloadData. If the table is scrolling duringthe time gap, the app may Crash!!!!
WRONGWAY:
Following
codes is WRONG: eventhe reloadData is called in main thread, there is still a time gapbetween the dataSource change and reloadData. If the table isscrolling during the time gap, the app mayCrash!!!!
wrongcodes
samples:
-(void)changeDatasource_backgroundThread
{
@autoreleasepool{
[self.dataSourceArray removeAllObjects];
[self.tableViewperformSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
}
}
RIGHTWAY:
Principle:
Always changedataSource in MAIN threadand call the reloadData immediately afterit.
Option1: If
the operation to change thedataSource should be executed in background, the operation cancreate a temp dataSource array and pass it to main thread withnotification, the main thread observes the notification, assign the tmpDataSource to dataSource and
reloadthe tableView by reloadData.
Option2: In
the background, call the GDCdispatch_async to send the two methods to mainthread together.
dispatch_async(dispatch_get_main_queue(),^{
self.dataSourceArray=a
new Array.
[self.tableView reloadData];
});
相关文章推荐
- UITableView reloadData的正确方法。
- UITableView reloadData的正确方法
- UITableView reloadData的正确方法
- UITableView reloadData的正确方法
- UITableView reloadData的正确方法。请每一个开发者必看。
- UITableView reloadData的正确方法
- 我的处女贴: UITableView reloadData的正确方法。请每一个开发者必看。《转》
- 我的处女贴: UITableView reloadDa…
- UITableView的reloadData方法,不执行cellForRow方法,
- swift UITableView具体使用方法
- iOS UITableView reloadData 时视图漂移或者闪动解决方法
- iOS UITableView reloadData 视图漂移或者闪动解决方法
- UITableView reloadData后,cellForRowAtIndex方法未调用问题
- UITableView 的全部代理方法
- UITableView的reloadData方法,不执行cellForRow方法,但是执行了numberOfRows和heightForRow方法
- 判断UitableView reloadData 结束的方法
- IOS 正确响应嵌套的uiscrollview的…
- UIScrollView && UITableView相关属性汇总及常用方法
- IOS 如何让UITableVIew的行纪录 不…
- 由UITableView reloadData后引起的界面布局问题分析