UITableViewCell 的重用機制
UITableView(表格) 的內容是靠個別的 UITableViewCell 物件所來呈現的,假設資料有成千上萬筆的話,那不就要產生成千上萬個物件,當然不可能!如此應用程式可是會因記憶不足而 Crash 掉的,為了避免這樣的情形發生,才會有這樣的機制出現,該機制不只適用在 UITableView 上,在 UIMapView 上的 Pin 也是利用此機制的。所以 UITableView 到底會產生幾個 UITableViewCell 來重用呢?答案是瑩幕的可視範圍+1個,例如畫面的高度可呈現 4 個 UITablViewCell,則重用的 UITableViewCell 則為 4+1 個,這 5 個 UITableViewCell 會不斷的輪迴被使用,不會生成新的 UITableViewCell 出來。法蘭克今天就要來說明如何使用重用機制。
首先查看官方的 API,重用機制有兩種方法:
在開始說明這兩個方法之前,先來了解一下 dequeue 的意思, dequeue 等於「to remove from a queue」,也就是從佇列中移出的意思。講白話一點就是呢,當我們在手機上向下滑動時,此時 UITableView 為了要顯示下一個 UITableViewCell,它會將即將要消失的 UITableViewCell(最上面的) 移出佇列給即將要顯示的 UITableViewCell(最下面) 使用,而不是一直產生新的物件。停下來稍微想一下懂了之後再繼續往下看。
1. func dequeueReusableCell(withIdentifier identifier: String) -> UITableViewCell?
根據官方的說明 => 使用代理的機制去獲取一個已經被分配的 cell,而不是去分配一個新的 cell,該 func 會回傳一個 optional 的值,也就是說可能會取不到,所以我們就可利用該回傳值來判斷是否要生成一個新的 cell。
第 4 行 => 宣告要被顯示在畫面上的資料。
第 24 ~ 35 行 => 透過 UITableView.dequeueReusableCell(withIdentifier: “Cell”) 來獲取一個 cell,第 26 行若是取不到則生成 UITableViewCell。
以上這種方法是在比較早期所使用的,在 IOS6 之後出現了另一種比較便捷的方法 2。
2. func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell
根據官方的說明 => 該方法相較於第一個方法,它的返回值不為 optional,意昧著它一定有值。不過在生成 UITableView 的同時,即要註冊 UITableViewCell 以確保在呼叫該方法的時侯一定取得到值。
第 9 行 => 相對於第一個方法,在生成 UITableView 的同時即要註冊 UITableViewCell(若是使用 Storyboard 則不需在這邊使用 code 註冊)。
第 24 ~ 30 行 => 透過 tableView.dequeueReusableCell(withIdentifier: “Cell”, for: indexPath) 來獲取一個 cell,該方法在呼叫的同時它會去 indexPath 裡去尋找是否已存在 UITableViewCell,若不存在會自動生成,若存在則直接返回,所以它一定會有回傳值,相對於第 1 個方法,在這就不用判斷是否為 nil 來決定是否生成 UITableViewCell。不過這邊值得注意的是 withIdentifier 的名稱必須和 register 的 forCellReuseIdentifier 一致,否則應用程式可是會 Crash 掉的,不妨試著將 register 的 forCellReuseIdentifier 改成不一致的名稱試試以加深印象。
結論:
法蘭克介紹的方式並沒有使用 Stroyboard,若是使用 Storyboard 則採用第二種方式即可,但務必記得一定要設定唯一的 UITableViewCell 的 Identifier,並且也要記得在呼叫 tableView.dequeueReusableCell(withIdentifier: “Cell”, for: indexPath) 填入和 Storyboard 相同的識別字。