UITableView-hightForRow调用时刻-Cell行高计算和缓存Cell行高
一、hightForRow调用时刻
这个方法的特点:
1.默认情况下
1> 每次刷新表格时,有多少数据,这个方法就一次性调用多少次(比如有100条数据,每次reloadData时,这个方法就会一次性调用100次)
2> 每当有cell进入屏幕范围内,就会调用一次这个方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
}
二、Cell行高计算和缓存Cell行高
①用全局属性统计计算:
/** 用来缓存cell的高度(key:模型,value:cell的高度) */ @property (nonatomic, strong) NSMutableDictionary *cellHeightDict; - (NSMutableDictionary *)cellHeightDict { if (!_cellHeightDict) { _cellHeightDict = [NSMutableDictionary dictionary]; } return _cellHeightDict; } //Cell行高计算和缓存Cell行高 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { HKTopic *topic = self.topics[indexPath.row]; NSString *key = topic.description; CGFloat cellHeight = [self.cellHeightDict[key] doubleValue]; if (cellHeight == 0) { // 这个模型对应的cell高度还没有计算过 // 文字的Y值 cellHeight += 55;//顶部头像+margin // 文字的高度 CGSize textMaxSize = CGSizeMake(SCREEN_WIDTH - 2 * HKMargin, MAXFLOAT); cellHeight += [topic.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil].size.height + HKMargin; // 工具条 cellHeight += 35 + HKMargin; // 存储高度 self.cellHeightDict[key] = @(cellHeight); // [self.cellHeightDict setObject:@(cellHeight) forKey:key]; HKLog(@"%zd %f", indexPath.row, cellHeight); } return cellHeight; } //最后在请求成功时,删除缓存 // 清除之前计算的高度 [self.cellHeightDict removeAllObjects];
②利用模型属性计算和缓存Cell行高
/** 所有的帖子数据 */ @property (nonatomic, strong) NSMutableArray<HKTopic *> *topics; //HKTopic数据模型类: //HKTopic.h 声明一个属性用来缓存Cell行高 /* 额外增加的属性(并非服务器返回的属性,仅仅是为了提高开发效率) */ /** 根据当前模型计算出来的cell高度 */ @property (nonatomic, assign) CGFloat cellHeight; //HKTopic.m @implementation HKTopic - (CGFloat)cellHeight { // 如果已经计算过,就直接返回 if (_cellHeight) return _cellHeight; JKFunc; // 文字的Y值 _cellHeight += 55; // 文字的高度 CGSize textMaxSize = CGSizeMake(SCREEN_WIDTH - 2 * HKMargin, MAXFLOAT); _cellHeight += [self.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil].size.height + HKMargin; // 工具条 _cellHeight += 35 + HKMargin; return _cellHeight; } @end //使用: /** 这个方法的特点: 1.默认情况下 1> 每次刷新表格时,有多少数据,这个方法就一次性调用多少次(比如有100条数据,每次reloadData时,这个方法就会一次性调用100次) 2> 每当有cell进入屏幕范围内,就会调用一次这个方法 */ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // HKTopic *topic = self.topics[indexPath.row]; // return topic.cellHeight; return self.topics[indexPath.row].cellHeight; }
三、estimatedRowHeight估算行高的作用:
// 设置cell的估算高度(每一行大约都是estimatedRowHeight) self.tableView.estimatedRowHeight = 200; // 所有cell的高度 -> contentSize.height -> 滚动条长度 // 1000 * 20 -> contentSize.height -> 滚动条长度 // contentSize.height -> 200 * 20 -> 16800 /* 使用estimatedRowHeight的优缺点 1.优点 1> 可以降低tableView:heightForRowAtIndexPath:方法的调用频率 2> 将【计算cell高度的操作】延迟执行了(相当于cell高度的计算是懒加载的) 2.缺点 1> 滚动条长度不准确、不稳定,甚至有卡顿效果(如果不使用estimatedRowHeight,滚动条的长度就是准确的) */ /** 这个方法的特点: 1.默认情况下(没有设置estimatedRowHeight的情况下) 1> 每次刷新表格时,有多少数据,这个方法就一次性调用多少次(比如有100条数据,每次reloadData时,这个方法就会一次性调用100次) 2> 每当有cell进入屏幕范围内,就会调用一次这个方法 2.设置estimatedRowHeight的情况下 1> 用到了(显示了)哪个cell,才会调用这个方法计算那个cell的高度(方法调用频率降低了) */ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // HKTopic *topic = self.topics[indexPath.row]; // return topic.cellHeight; return self.topics[indexPath.row].cellHeight; } -(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { return self.topics[indexPath.row].cellHeight; }