UITableView 在请求数据后调用reloadData只走numberOf相关代理,不走cellForRowAtIndexPath和HeightForRow等代理的坑。
我们在修改TableView的数据后,经常使用下面这句
[self.tableView reloadData]
来更新UI
但这里埋了一个坑,这句代码执行后, 按理说,应该执行numberOfRowsInSection和CellForRow方法,
测试结果却是代码立即返回,即,整个过程是异步的.
Reload Begin
numberOfRowsInSection
Reload End
cellForRowAt
heightForRow
- 1.如上所示,调用reloadData 之后,立即调用numberOfRowsInSection,但是cellForRowAt和heightForRow 是异步调用,
回到当前RunLoop,布局cell时才会被调用.
reloadData 这样的特性就导致了没有及时调用相对应的代理方法,
如果在reloadData之后,我们想要执行某些操作,就会导致出现不可预见的结果.
并没有什么不好,异步执行能让cellForRow中的耗时操作在子线程处理,立即返回. 问题就出在,如果我们想要在reloadData之后,做一些操作。
比如主动调用cellForRow方法获取某一个Row对应的cell,那么有很大几率是失败的. 因为之前cellForRow方法可能还没有返回呢,这时候就要用到强制布局刷新了
-
2.想要调用reloadData 之后立即调用所有代理方法,我们可以添加layoutIfNeeded 让TableView强制布局
-
3.reloadData方法只能被主线程调用。不能被其他线程调用。所以不需要@synchronized。如果你想要其他线程通过主线程间接调用reloadData。代码如下:
[self.tableView performSelectorOnMainThread:@selector(reloadData)withObject:nil
waitUntilDone:NO];
- 4.如果在调用reloadDate方法后需要立即获取tableview的cell、高度,或者需要滚动tableview,那么,直接在reloadData后执行代码是有可能出问题的。
因为reloadDate并不会等待tableview更新结束后才返回,而是立即返回,之后再计算表高度,获取cell(主线程中)。
如果表中的数据非常大,在一个run loop周期没执行完,这时,需要tableview视图数据的操作就会出问题了。
apple并没有直接提供reloadData的api,想要程序延迟到reloadData结束在操作,可以用以下方法
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
//刷新完成 layoutIfNeeded会强制重绘并等待完成。
方法2:
[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
//刷新完成
});
网友评论