在我们日常的开发过程中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)
}