Paste_Image.png
I have a TableView that shows each row what row it is, and now I want to dynamically add two rows below it every time I press the Update button. To do this, simply change the data source and refresh the list:
// tableData = ["0", "1", "2", "3"]
@IBAction func update(_ sender: AnyObject) {
tableData.append("\(tableData.count)")
tableData.append("\(tableData.count)")
tableView.reloadData()
}Copy the code
As you can see from your knees, this will refresh the first four rows that have not been changed, causing unnecessary performance loss. A better way to do this is:
// 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()
}Copy the code
This causes the func tableView(_ tableView: UITableView, cellForRowAt indexPath: indexPath) -> UITableViewCell method to be called four times less than above.
The function of the beginUpdates and endUpdates methods here is to aggregate the insert/delete operations on the tableView between these two statements and then update the UI at the same time. Since I’m only doing an INSERT here, it’s okay to remove these two statements, but it should be done for the sake of specification, because code like this will crash at runtime if it’s customary not to:
@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()
}Copy the code
Because after the first insert, the total numberOfRows on the UI is trying to change from 4 to 5, while the data source is 6, it checks to see if the user’s UI operations on the tableView match the values fetched by the numberOfRows method.
conclusion
NumberOfRows method calls: The numberOfRows method is called only once
ReloadData will call the cellForRow method for all currently displayed cells, updates will only call the cellForRow method for newly added cells: ReloadData will call the cellForRow method asynchronously at some point after the numberOfRows method is called, and Updates will call the cellForRow method immediately after the numberOfRows method is called
Defects: deleteRows will not call the cellForRow method, which may cause the display to be inconsistent with the data source. Manually ensure that the numberOfRows after insertRows and deleteRows matches numberOfRows, otherwise it will crash at runtime
Part of the article is not written, the summary mentioned part in the full demo inside: Demo Github address