iOS: 如何知道reloadData() 完成了它的任务?

iOS: How to know reloadData() was completed its task?

我想滚动到给定索引 (self.boldRowPath),但是当我调试时 scrollToRowreloadData() 之前执行。

如何知道reloadData已经完成?

func getAllTimeEvent()  {
    self.arrAllTimeEvent = ModelManager.getInstance().getAllTimeEvent(from: self.apportmentDateFrom, to: self.apportmentDateTo)
    self.tblTimeEvent.reloadData()
    self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
 }

任何帮助将不胜感激。

尝试这样做,它应该有效:

self.tblTimeEvent.reloadData()
DispatchQueue.main.async(execute: {
    self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
})

这将在主线程上执行 scrollToRow,这意味着在 reloadData 完成后(因为它在主线程上)

你可以做出一个非常可靠的假设,即当最后一次为屏幕上的可见部分调用 tableView(_:willDisplay:forRowAt:) 时,UITableView 已完成重新加载。

所以尝试这样的事情(对于第 0 部分中的行占用屏幕上可用 space 的 tableView):

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
  let lastRowIndex = tableView.numberOfRows(inSection: 0)
  if indexPath.row == lastRowIndex - 1 {
    // tableView done reloading
    self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
  }
}

this answer 中所述,UITableView 的重新加载发生在下一个布局 运行 上(通常,当您 return 控制 运行 环形)。

因此,您可以使用主调度队列在下一个布局之后安排代码。你的情况:

    func getAllTimeEvent()  {
        self.arrAllTimeEvent = ModelManager.getInstance().getAllTimeEvent(from: self.apportmentDateFrom, to: self.apportmentDateTo)
        self.tblTimeEvent.reloadData()
        DispatchQueue.main.async {
            self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
        }
    }

您也可以通过手动调用layoutIfNeeded强制布局。但这通常不是一个好主意(以前的选择是最好的):

    func getAllTimeEvent()  {
        self.arrAllTimeEvent = ModelManager.getInstance().getAllTimeEvent(from: self.apportmentDateFrom, to: self.apportmentDateTo)
        self.tblTimeEvent.reloadData()
        self.tblTimeEvent.layoutIfNeeded()
        self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
    }

您可以使用...确保重新加载完成...

在 Swift 3.0 + 中,我们可以为 UITableView 创建一个带有 escaped Closure 的扩展,如下所示:

extension UITableView {
    func reloadData(completion: @escaping () -> ()) {
        UIView.animate(withDuration: 0, animations: { self.reloadData()})
        {_ in completion() }
    }
}

并像下面一样使用它:

Your_Table_View.reloadData {
   print("reload done")
 }

希望这对某人有所帮助。干杯!

tableView.reloadData { [weak self] in
    self?.doSomething()
}

您可以为此使用 CATransaction

CATransaction.begin()
CATransaction.setCompletionBlock {
    // Completion
}
tableView.reloadData()
CATransaction.commit()