在我們日常的開發過程中tableview 是十分常見的UI 控件之一。什麼是Tableview?
在衆多移動應⽤用中,能看到各式各樣的表格數據 。
在iOS中,要實現表格數據展示,最常用的做法就是使用UITableView,UITableView繼承自UIScrollView, UITableView繼承自UIScrollview,是蘋果爲我們封裝好的一個基於scroll的控件。因此支持垂直滾動,⽽且性能極佳 。
UITableview有分組和不分組兩種樣式,可以在storyboard或者是用代碼設置。
上面主要是一個個的 UITableViewCell,可以讓UITableViewCell響應一些點擊事件,也可以在UITableViewCell中加入 UITextField或者UITextView、UILable等子視圖,使得可以在cell上進行文字編輯與顯示。
UITableView中的cell可以有很多,一般會通過重用cell來達到節省內存的目的:通過爲每個cell指定一個重用標識符 (reuseIdentifier),即指定了單元格的種類,當cell滾出屏幕時,會將滾出屏幕的單元格放入重用的queue中,當某個未在屏幕上的單 元格要顯示的時候,就從這個queue中取出單元格進行重用。
但對於多變的自定義cell,有時這種重用機制會出錯。比如,當一個cell含有一個UITextField的子類並被放在重用queue中以待重 用,這時如果一個未包含任何子視圖的cell要顯示在屏幕上,就會取出並使用這個重用的cell顯示在無任何子視圖的cell中,這時候就會出錯。
//我們在網上經常看到這樣的寫法 來註冊一個tableview
// 註冊nib
let nib = UINib.init(nibName: "NibTableViewCell", bundle: nil)
tableView?.register(nib, forCellReuseIdentifier:"NibTableViewCell")
//使用的時候然後這樣寫
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"NibTableViewCell")
return cell!
}
//這樣做的根本上內存消耗是最小的,因爲這樣做小化的初始化了可用 的cell,減少了內存的開銷
但是這種做法需要對cell 內的子視圖做重新的賦值 切記的的是隻寫了 if 理所當然的認爲 else 下 就是初始化時的狀態。比如在xib 內設置的顏色
如下圖
這裏就是隻寫了 進行中時 設置爲綠色,天真的以爲 結束時是就是當初在xib 上設置的默認色
針對上面的問題有三種種解決方案
1.是 不改變 cell 的 identifier
對cell 上面的子視圖做全賦予 ,即 每種狀態的賦值都應重新賦予
2.動態的對cell 的 identifier進行賦值 做到當前頁面的cell 的唯一性,
//使用的時候然後這樣寫
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
// 註冊nib
let nib = UINib.init(nibName: "NibTableViewCell\(IndexPath.row)", bundle: nil)
tableView?.register(nib, forCellReuseIdentifier:"NibTableViewCell")
let cell = tableView.dequeueReusableCell(withIdentifier:"NibTableViewCell\(IndexPath.row)")
return cell!
}
3.不調用重用機制 ,重用機制調用的就是dequeueReusableCellWithIdentifier這個方法,方法的意思就是“出列可重用的cell”,因而只要將它換爲cellForRowAtIndexPath(只從要更新的cell的那一行取出cell),就可以不使用重用機制,因而問題就可以得到解決,雖然可能會浪費一些空間。
var cell: UITableViewCell? = tableView.cellForRow(at: indexPath)
//根據indexPath準確地取出一行,而不是從cell重用隊列中取出
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: CellIdentifier)
}