iOS-列表reload异步刷新

「这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

问题

可能大部分程序员再开发中对于tableView的reloadData方法是异步执行的不太了解, 但是他确实是异步执行的. 同其他的异步函数一样, 执行完reloadData之后就会 tableView布局, cell的显示以及高度计算 和代理 等一些其他的代码, 因为是异步的, 所以就不会阻塞主线程.

所以reloadData并不会等tableView的代理以及其他的函数执行完毕之后才会返回, 而是立即返回的.

因此我们并无法准确的知道reloadData完成的时机,从而无法及时的处理下一步的操作

尤其是再tableView有很多的数据以及布局比较复杂的情况下, 在reloadData没有执行完毕, 然后就去调用之后的代码的话很可能就出现一些意向不到的问题

 self.tableView?.reloadData()
self.tableView?.scrollToRow(at: IndexPath.init(row: self.selectedIndex, section: 0), at: .none, animated: true)
复制代码

好比上面这段代码, 就是一个错误的案例, 如果reloadData还没有执行完毕, 那么就要求滚动到指定的行数, 那么必然会出现错误的, 当然还有很多其他的场景存在

解决

那么如果解决上诉的问题呢?

如果可以获取到reloadData的时机,那么就不会出现上述的问题, 可以精准的执行后续的操作, 而不会导致出现问题

1.layoutIfNeeded

使用 layoutIfNeeded 来进行强制重绘,就可以获取到reloadData完成后的时机, 但是有一个问题就是, 使用 layoutIfNeeded 会导致主线程阻塞, 用户的感觉就是卡顿, 这也是一个不好地方所在

self.tableView?.reloadData()
self.tableView?.layoutIfNeeded()
复制代码

2.DispatchQueue.main.async

使用 DispatchQueue.main.async 的方式,简单来说就等等主线程空间的时候 再进行操作, 相对来说还是推荐这种方式;

self.tableView?.reloadData()
DispatchQueue.main.async {
    self.tableView?.scrollToRow(at: IndexPath.init(row: self.selectedIndex, section: 0), at: .none, animated: true)
}
复制代码

结语

一般情况下 我们再写tableView的时候还是不太会遇到这情况, 除非cell上的布局特别的复杂, 其实也可以通过别 的方式来避免这种情况的方式, 好比通过内存换速度的方式等, 如果文章对你有帮助的话, 给个赞吧!

猜你喜欢

转载自juejin.im/post/7032681321256189982