在iOS项目开发中会遇到这样一个问题:确定cell的高度。对于cell高度固定的页面来说这个很好办直接在heightForRowAtIndexPath方法中返回固定的一个数值就行。然而对于cell高度不固定的页面来说却需要我们开发人员计算出cell的高度。
笔者之前通常会会将计算cell高度的代码放在heightForRowAtIndexPath方法中,看代码:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
TopicModel * model = self.dataSource[indexPath.row];
cellHeight == 0.f
cellHeight += 30;
NSString * text = model.text;
NSMutableDictionary * dic = [NSMutableDictionary dictionary];
dic[NSFontAttributeName] = [UIFont systemFontOfSize:17];
CGRect textRect = [text boundingRectWithSize:CGSizeMake(WIDTH-20, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil];
cellHeight += textRect.size.height;
cellHeight += 30;
return cellHeight;
}
上面的代码虽然能计算出cell的高度实现想要的效果,可会有一个耗性能的问题:即使之前计算过某个cell的高度,在这个cell在此展示出来的时候还会再次调用heightForRowAtIndexPath这个方法,从而再次地计算这个cell的高度。这样就会进行多余的操作,造成资源的浪费。在这种情况下,我们应该将之前计算出的cell高度进行缓存,下次这些cell要再次展示的时候就从缓存中获取之前计算出的cell高度,而不用进行多余的计算操作。
我们利用字典对cell高度进行缓存,而且为了区分每个cell,我们将每个cell对应的模型的唯一标识description作为字典的key。代码:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
TopicModel * model = self.dataSource[indexPath.row];
CGFloat cellHeight = [self.cellHeightDic[model.description] floatValue]; // 从字典中取出cell的高度
if (cellHeight == 0.f) { // 如果字典中没有存储cell的高度
cellHeight += 30;
NSString * text = model.text;
NSMutableDictionary * dic = [NSMutableDictionary dictionary];
dic[NSFontAttributeName] = [UIFont systemFontOfSize:17];
CGRect textRect = [text boundingRectWithSize:CGSizeMake(WIDTH-20, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil];
cellHeight += textRect.size.height;
cellHeight += 30;
// 将cell的高度存储到字典中
[self.cellHeightDic setObject:@(cellHeight) forKey:model.description];
// NSLog(@"%f", cellHeight);
}
return cellHeight;
}
为了更完善些,我们还应该在下拉刷新tableview执行reloadData之后将存储cell高度的字典清空以防字典中的数据越来越多。