关于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)
}

 

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