關於tableview cell 重用機制理解 與cell 內容重複問題解決

  在我們日常的開發過程中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)
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章