UITableView 是我们在日常开发中经常会用到的控件,cell 的高度计算也一直是我们不可逃避的关键步骤,我们主要有以下两种方法做高度计算。
1:手动计算。
通过界面布局以及自己的业务需求 在数据模型层完成 整个 cell 的高度计算,并将结果存储到 对应的数据模型中,在tableView 的协议方法中返回即可。
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let model = showModels[indexPath.row]
return model.cellHeight
}
//计算文本标签的size的方法:
let dic = NSDictionary(object: font, forKey: NSFontAttributeName as NSCopying)
let strSize = string.boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: dic as? [String : AnyObject], context:nil).size
2:自动计算
我们也可以设置系统自动为我们计算cell 的高度,更方便快捷减少操作的复杂度。
tableView.rowHeight = UITableViewAutomaticDimension
或者在协议方法中设置:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
在 swift 中,结合 snpkit 做cell 高度自适应时一定要保证cell 中最下面的控件 与 cell 底部关联上。
系统自动计算时,会发现系统并没有做高度的缓存会导致很多重复的高度计算操作。那么我们如何在使用系统自动计算的方式的同时避免重复计算呢?
仔细研究代码发现系统在自动计算时,会调用方法:
@available(iOS 8.0, *)
open func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize
该方法直接返回对应 indexPath 系统计算完后的 cell 高度, 我们可以在 在 forCell 的协议方法中,调用改 自动计算的函数提前获取到 cell 的对应高度并完成存储。
//tableview协议方法
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! Cell
//赋值cell
let mdoel = showModelArray[indexPath.row]
cell.reloadView(cellModel: mdoel)
//获取并存储 系统自动计算的 cell 高度
let cellHeight = cell.systemLayoutSizeFitting(CGSize.init(width: tableView.bounds.width, height: 0), withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityFittingSizeLevel).height
model.cellHeight = cellHeight
return cell
}
然后在赋值 高度的协议方法中 返回 存储高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let model = showModels[indexPath.row]
return model.cellHeight ? UITableViewAutomaticDimension : model.cellHeight!
}