简介:
UITableView的reloadData是异步的,在调用该方法后,会继续执行其它代码(tableView的布局、cell的显示和高度计算等代理方法,或者自己的一些代码等),不会阻塞主线程;即reloadDate并不会等待tableview更新结束后才返回,而是立即返回。这样就会导致无法确定reloadData后完成的时机,无法在reloadData完成后及时的做其它操作(例如滚动到指定单元格);如果表中的数据比较大或者布局比较复杂,在一个run loop周期没执行完,这时,需要对tableview视图数据的操作,就会出问题了(例如滚动到指定单元格)。
问题代码如下:
self.tableView?.reloadData()
self.tableView?.scrollToRow(at: IndexPath.init(row: self.selectedIndex, section: 0), at: .none, animated: true)
怎样解决这个问题呢,即怎么获取reloadData完成的时机呢?有三种方法,这三种方法的实现和原理如下:
方法一:reloadData后调用layoutIfNeeded
实现:
self.tableView?.reloadData()
self.tableView?.layoutIfNeeded()
layoutIfNeeded会强制重绘,阻塞主线程,等待tableView的reloadData更新布局后,进行layoutIfNeeded的以后的代码,坏处是会阻塞主线程,造成不必要的卡顿。
方法二:reloadData后调用DispatchQueue.main.async方法
实现:
self.tableView?.reloadData()
DispatchQueue.main.async {
self.tableView?.scrollToRow(at: IndexPath.init(row: self.selectedIndex, section: 0), at: .none, animated: true)
}
DispatchQueue.main.async等待主线程空闲时(在reloadData后,不在主线程做其它操作),即使tableView进行reloadData更新布局后调用,不会阻塞主线程,推荐使用该方法。
方法三:UIView.animate中调用reloadData,结束后再进行其它操作
实现:
UIView.animate(withDuration: 0.25) {
self.tableView?.reloadData()
} completion: { (isFinish) in
if isFinish {
self.tableView?.scrollToRow(at: IndexPath.init(row: self.selectedIndex, section: 0), at: .none, animated: true)
}
}
UIView.animate利用completion等待动画操作reloadData完成后调用。
网友评论