UITableView的优化方案

谈起UITableView大家都不会陌生,因为这个视图太重要了,基本上每个App都离不开它的身影,其实它算是一个比较复杂的视图了,每个UITableView都有一个tableViewHeaderView, 我们能在tableHeaderView上面显示一些比较重要且特别的东西,比如轮播图。一个tableview包含一个到多个section,一个section又包含

一个header,一个footer和cells组成。这样复杂的视图结构,处理和渲染起来一定会给内存造成很大的压力,如果我们在开发的时候不对它做一些单独的处理,滑

动起来的时候就很可能赞成卡顿的现象,尤其是在cell里面有图片的情况。针对页面卡顿的情况,个人觉得可以从以下几个方面进行优化:

1、重用机制

2、懒加载

3、尽量不要使用不透明视图

4、善用drawRect(减少视图数目)

5、缓存cell高度

6、滑动不加载

前四种方式比较简单,这里就不在做过多的赘述,只是需要注意cell被重用时,它内部绘制的内容并不会被自动清除,因此你可能需要调用setNeedsDisplayInRect:或setNeedsDisplay方法。

这里主要介绍以下cell高度的缓存和滑动不加载两种方式:

缓存cell高度主要是利用到了策略模式,将计算cell高度的代码单独抽离出来,其中cell缓存高度的代码如下:

首先我们需要建一个模型类,用来接收缓存的cell高度,下面是模型的.h文件:


ViewController中的代码如下:

#import "ViewController.h"
#import "HeightModel.h"

@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>{
    NSMutableArray *_data;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _data = [NSMutableArray array];
    NSString *string = @"李白(701年2月8日—762年12月)[1]  ,字太白,号青莲居士,又号“谪仙人”,汉族,绵州昌隆县(今四川省江油市)人,是唐代伟大的浪漫主义诗人,被后人誉为“诗仙”。与杜甫并称为“李杜”,为了与另两位诗人李商隐与杜牧即“小李杜”区别,杜甫与李白又合称“大李杜”。其人爽朗大方,爱饮酒作诗,喜交友。";
    for (int i = 0; i < 20; i++) {
        //造假数据
        NSInteger num = arc4random() % string.length;
        NSString *subString = [string substringToIndex:num];
        //开始计算文字高度
        CGFloat height = [self labelAutoSizeWithText:subString Font:14 MaxSize:CGSizeMake(300, 10000)].height;
        HeightModel *model = [HeightModel new];
        model.text = subString;
        model.cellHeight = [NSString stringWithFormat:@"%f",height];
        [_data addObject:model];
    }
}

//返回size的方法
- (CGSize)labelAutoSizeWithText:(NSString *)text Font:(NSInteger)font MaxSize:(CGSize)maxSize {
    NSDictionary *dic = @{
                          NSFontAttributeName:[UIFont systemFontOfSize:font]
                          };
    return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine attributes:dic context:nil].size;
}

#pragma mark -- UItableViewDelegate UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _data.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    HeightModel *model = _data[indexPath.row];
    return [model.cellHeight floatValue] + 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 0)];
        [label setNumberOfLines:0];
        [label setTag:123];
        [label setFont:[UIFont systemFontOfSize:14]];
        [cell.contentView addSubview:label];
    }
    HeightModel *model = _data[indexPath.row];
    //找到label
    UILabel *label = (UILabel *)[cell.contentView viewWithTag:123];
    //修改label 的frame
    [label setFrame:CGRectMake(10, 10, 300, [model.cellHeight floatValue])];
    //为label赋值
    label.text = model.text;
    label.backgroundColor = [UIColor colorWithRed:arc4random() % 255 / 256.0 green:arc4random() % 255 / 256.0 blue:arc4random() % 255 / 256.0 alpha:1];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;
}

以上就是cell高度缓存的方法,下面我们再来介绍以下滑动不加载的方法:

首先我们要创建一个模型,模型的.h文件如下


然后我们再创建一个cell,创建cell我用的时xib的方法,cell中的代码如下:

在cell的.h文件提供对模型赋值的方法,这样做可以减少controller的压力,尤其是tableView:cellForRowAtIndexPath这个代理方法的压力,


cell的.m文件如下


tableViewController的.m中代码如下:

#import "ViewController.h"
#import "ImageCell.h"
#import "ImageModel.h"
#define kImageUrl @"http://h.hiphotos.baidu.com/image/h%3D300/sign=0e698f82d643ad4bb92e40c0b2025a89/03087bf40ad162d92589103b16dfa9ec8a13cdb6.jpg"
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource> {
    NSMutableArray *_data;
}
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _data = [NSMutableArray array];
    NSArray *array = @[@{@"picUrl":kImageUrl},@{@"picUrl":kImageUrl},
                       @{@"picUrl":kImageUrl},@{@"picUrl":kImageUrl},
                       @{@"picUrl":kImageUrl},@{@"picUrl":kImageUrl},
                       @{@"picUrl":kImageUrl},@{@"picUrl":kImageUrl}
                       ];
    for (NSDictionary *dic in array) {
        ImageModel *model = [[ImageModel alloc] init];
        [model setValuesForKeysWithDictionary:dic];
        model.isLoad = NO;
        [_data addObject:model];
    }
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self loadShowCells];
    });
}


//加载可见cell 请求数据
- (void)loadShowCells {
   NSArray *array = [self.tableView indexPathsForVisibleRows];
    for (NSIndexPath *indexPath in array) {
        //1、获取cell
        ImageCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
        ImageModel *model = _data[indexPath.row];
        [cell setImageWithModel:model];
    }
}

#pragma mark UIScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self loadShowCells];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        [self loadShowCells];
    }
}

#pragma mark UITableViewDelegate UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _data.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier = @"ImageCell";
    ImageCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[NSBundle mainBundle] loadNibNamed:@"ImageCell" owner:self options:nil].lastObject;
    }
    ImageModel *model = _data[indexPath.row];
    if (model.isLoad) {
        //此时执行的这个方法是在缓存中提取
        [cell setImageWithModel:model];
    } else {
        //显示占位图
        [cell setImageWithModel:nil];
    }
//对cell进行赋值
//    ImageModel *model = _data[indexPath.row];
//    [cell setImageWithModel:model];
    return cell;
}

这样就做好了UITableView的全部优化,做到了上面六点,你的tableView应该很流畅了吧!






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值