今天要來講講update們。
會有這系列的function,是因為一個小故事。
之前有說過,row的位置是table藉由計算每個cell的高度來決定下一個row生成的的位置。而表格資料更新時,table並不會即時更新,而是要等reload的時候才會依據新的data更新表格。
現在問題來了:如果第2列的資料做了會更動到列高的更新,但只有第4列單獨被reload的時候,會發生什麼事情?
由於第4列被reload,table會根據前4列的data重新計算高度來決定第4列要被reload的位置,而第2列做了會更動到列高的更新,因此第4列的位置會和reload前不同。
but! 就是那個but,我只有第4列被reload,代表前面4列的狀態都是不變的,但第4列的位置變更了,所以就會發生,要馬第4列疊到第3列,要馬跟第3列中間有間隔的慘劇,因此app就crush了。
於是救世主就出現了,他的名字叫做performBatchUpdates(_:completion:),前身是beginUpdates()和endUpdates()的集合體。
performBatchUpdates(_:completion:)是一個可以讓insert、delete、move、reload以及與seleting相關的動作(像是 cellForRow(at:)和indexPathsForVisibleRows)結合在一起,或是可以在不reload table的情況下對列高進行變更的function。
此function的第一個區塊就是beginUpdates()的內容,是一個不帶參數也沒有回傳值的closure,會依照一定的程序處理內部呼叫的function。例如他會先處理完所有delete再處理insert,不管你呼叫他們的順序為何,以避免在同一個動畫中,剛插入的data因為index錯亂又被刪除的問題。
所以剛剛的問題同樣可以靠performBatchUpdates(_:completion:)和beginUpdates()解決。當function處理reload的動作時,會先依舊的data算出row的位置、更新data之後進行reload,故不會有上述的情形發生。
而第二個區塊就是endUpdates()的內容,是帶一個布林值且沒有回傳值的closure,實行所有操作完成時的後續處理。如果所帶的布林值為false,代表動畫因任何原因中斷。
為sectionIndexMinimumDisplayRowCount指定一個Int,定義顯示在表格右緣的表格列索引數字。
這個property只有在表格style為plain的時候才會生效,預設值為0。
使用sectionIndexColor指定索引的顏色,並使用sectionIndexBackgroundColor指定索引的背景顏色,nil則代表系統的default color。
先前有示範過reload rows,是使用reloadRows(at:with:)給定要reload的row詳細的indexPath,搭配一個RowAnimation。
例如我們對button指定更改陣列裡的資料,並且reload該列:
@objc func changeDataAction(_ sender: UIButton) {
data[1] = "data changed"
newTableView.reloadRows(at: [IndexPath(row: 1, section: 0)], with: .fade)
}
而如果沒有reload,則就算資料更改了,tableView也不會有所變更。
如果要reload section,則要使用reloadSections(_:with:)給定要reload的section位置並搭配一個RowAnimation。
而要reload整個table的話,使用reloadData()這個function,啊整個table都被更新了,就沒什麼好設定RowAnimation了。
下一回要講drag delegate和drop delegate。