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;
}

 

posted @ 2018-12-14 11:41  淡然微笑_Steven  阅读(463)  评论(0编辑  收藏  举报