UITableView自适应行高优化

iOS8之后,苹果推出了self-sizing cell的概念,旨在让cell自己负责自己的高度。我们对cell进行合理的约束之后,会自动通过-systemLayoutSizeFittingSize:的API计算出高度,但是系统的方法并不会对高度进行缓存,所以还存在优化的空间。

一般自适应:
 tableView.rowHeight = UITableView.automaticDimension
 tableView.estimatedRowHeight = 100      //行高的预估值,可以随便给

我们使用AutoLayout约束好cell内部的所有控件之后,只要指定tableview的rowHeightautomaticDimension,然后设置一个预估的行高estimatedRowHeight,不要去实现代理里的返回行高的方法,然后我们的cell就会自动计算出高度,但是经过验证,cell每次加载的过程中,高度需要重新计算,并没有得到缓存,这里我们可以做个高度的缓存,优化性能。

自适应高度+高度缓存
class ExampleModel: NSObject {
    
    var data: Dictionary?
    var rowHeigt: CGFloat?
    
}

我们在我们的数据model里加个行高的属性rowHeigt,这里设置为?可为空,后面用来判断这个model的行高是否计算过,避免重复计算。

var data = [ExampleModel]()    //tableview的数据源,写在controller的类内
extension ExampleViewController: UITableViewDataSource, UITableViewDelegate {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
        let model = data[indexPath.row]
        cell.setData(model: model)
        
        if model.rowHeigt == nil {
            
            //在model中缓存高度
            model.rowHeigt = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
            
        }
        
        return cell
        
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        
        let height = data[indexPath.row].rowHeigt
        return height == nil ? UITableView.automaticDimension : height!
        
    }
    
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100.0
    }
    
}
  • 我们在tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)的方法里,判断当前的行高是否计算过,计算过的话直接返回对应的行高,未计算的话,返回UITableView.automaticDimensio,让cell去自动计算。
  • 我们在tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell的方法里进行行高的缓存,放在这里的原因是,我们一般在这个方法里进行cell的数据赋值,赋值之后,我们调用systemLayoutSizeFitting这个系统的API进行对应行高的计算(ps:系统自动计算行高也是通过这个方法),这里我们也做了是否已有行高的判断,避免了重复计算。
  • systemLayoutSizeFitting这个方法,网上找到的帖子都说必须用cell.contentView,验证过了,直接用cell也可以,也不用必须像网上说的+1或者+0.5,直接出的结果也是比较准确的;这里传的参数UIView.layoutFittingCompressedSize是指可能得到的最小尺寸,也可以传一个自己设置的size进去。
  • estimatedHeightForRowAt我们这里用了delegate的方法返回,也可以直接赋值的,只要用到了automaticDimension,记得一定要设置这个属性的值。
总结:经过我们优化之后,第一次加载时候计算所得的高度,与数据源绑定并缓存,可以供后续显示以及刷新的使用,相当于把动态计算行高变成了固定行高,性能的优化立竿见影。

欢迎更正错误和交流,回复评论和私信皆可

你可能感兴趣的:(UITableView自适应行高优化)