美文网首页
话说 UITableView 的坑

话说 UITableView 的坑

作者: 平常心_kale | 来源:发表于2020-03-31 19:44 被阅读0次

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(), ^{
//刷新完成
});

相关文章

网友评论

      本文标题:话说 UITableView 的坑

      本文链接:https://www.haomeiwen.com/subject/wdwiuhtx.html