【iOS 開發】tableView updates 對比 reloadData

Paste_Image.png

如圖有一個 TableView,每行顯示這一行是第幾行,現在我希望每按一次 update 按鈕,就動態地在下方加兩行。那么簡單粗暴的做法是 ,更改數據源,然后刷新一下列表:

// tableData = ["0", "1", "2", "3"]
@IBAction func update(_ sender: AnyObject) {
    tableData.append("\(tableData.count)")
    tableData.append("\(tableData.count)")
    tableView.reloadData()
}

用膝蓋想也知道,這會使得前四行沒有被改動的地方也被刷新一遍,帶來了不必要的性能損耗。
好一點的做法是下面這樣的:

// tableData = ["0", "1", "2", "3"]
@IBAction func update(_ sender: AnyObject) {
    tableData.append("\(tableData.count)")
    tableData.append("\(tableData.count)")
    tableView.beginUpdates()
    let indexPaths = [IndexPath(row: tableData.count-2, section: 0), IndexPath(row: tableData.count-1, section: 0)]
    tableView.insertRows(at: indexPaths, with: UITableViewRowAnimation.automatic)
    tableView.endUpdates()
}

與上面相比,這樣做使得 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 方法被少調用了四次。

這里 beginUpdatesendUpdates 方法的作用是,將這兩條語句之間的對 tableView 的 insert/delete 操作聚合起來,然后同時更新 UI。鑒于我這里只進行了一次 insert 操作,把這兩條語句去掉也沒事,但是出于規范還是應該寫上,因為假如習慣不寫,下面這樣的代碼會運行時崩潰:

@IBAction func update(_ sender: AnyObject) {
    tableData.append("\(tableData.count)")
    tableData.append("\(tableData.count)")
    //        tableView.beginUpdates()
    tableView.insertRows(at: [IndexPath(row: tableData.count-2, section: 0)], with: UITableViewRowAnimation.automatic)
    tableView.insertRows(at: [IndexPath(row: tableData.count-1, section: 0)], with: UITableViewRowAnimation.automatic)
    //        tableView.endUpdates()
}

因為第一次 insert 之后,當前 row 的總數量在 UI 上試圖 4 變成 5,然而數據源是 6,它會檢查使用者對 tableView 的 UI 操作,最后是不是和 numberOfRows 方法獲取的值相對應。

總結

numberOfRows 方法調用: 都只調用一次 numberOfRows 方法

cellForRow 方法調用次數: reloadData 會為當前顯示的所有cell調用這個方法,updates 只會為新增的cell調用這個方法
cellForRow 方法調用時間: reloadData 會在 numberOfRows 方法調用后的某一時間異步調用 cellForRow 方法,updates 會在 numberOfRows 方法調用后馬上調用 cellForRow 方法

reloadData 方法缺陷: 帶來額外的不必要開銷,缺乏動畫
updates 方法缺陷:deleteRows 不會調用 cellForRow 方法,可能導致顯示結果與數據源不一致;需要手動保證 insertRows、deleteRows 之后,row 的數量與 numberOfRows 的結果一致,否則會運行時崩潰


部分文章中沒有寫,總結提到了的部分放在完整 demo 里面了:demo Github 地址

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容