web-dev-qa-db-ja.com

iOS:reloadData()がそのタスクを完了したことを知る方法は?

特定のインデックス(_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)
 }
_

どんな助けでも大歓迎です。

11
Harshil Kotecha

これを試してみてください、それはうまくいくはずです:

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

これはメインスレッドでscrollToRowを実行します。つまり、reloadDataが実行された後です(メインスレッド上にあるため)。

21
Farid Al Haddad

この答え で説明されているように、UITableViewのリロードは次のレイアウト実行時に行われます(通常、実行ループに制御を戻すとき)。

したがって、メインのディスパッチキューを使用して、次のレイアウトの後にコードをスケジュールできます。あなたの場合:

    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)
    }
5
Julien Quere

リロードが...を使用して行われていることを確認できます

In Swift 3.0 +以下のようなescaped Closureを使用してUITableViewの拡張を作成できます。

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

そして、あなたが望むどこでも以下のように使用してください:

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

これが誰かに役立つことを願っています。乾杯!

2
Chanaka Caldera

画面上の可視セクションに対して最後にtableView(_:willDisplay:forRowAt:)が呼び出されたときにUITableViewがリロードされたというかなり堅固な仮定を立てることができます。

したがって、次のようなものを試してください(セクション0の行が画面上の使用可能なスペースを占める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)
  }
}
1
Andy Obusek

そのためにCATransactionを使用できます

CATransaction.begin()
CATransaction.setCompletionBlock {
    // Completion
}
tableView.reloadData()
CATransaction.commit()
0
Igor Bachek
tableView.reloadData { [weak self] in
    self?.doSomething()
}
0
Giang