UITableView优化

        如果tabview要显示100个Cell,当前屏幕显示10个。那么刷新(reload)UITableView时,UITableView会先调用100次tableView:heightForRowAtIndexPath:方法,然后调用10次tableView:cellForRowAtIndexPath:方法;滚动屏幕时,每当Cell滚入屏幕,都会调用一次tableView:heightForRowAtIndexPath: tableView:cellForRowAtIndexPath:方法。所以优化tableview时,主要考虑这两个方法。

    1. 没有优化的版本

    

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     ContacterTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@ "ContacterTableCell" ];
     if  (!cell) {
         cell = (ContacterTableCell *)[[[NSBundle mainBundle] loadNibNamed:@ "ContacterTableCell"  owner:self options:nil] lastObject];
     }
     NSDictionary *dict = self.dataList[indexPath.row];
     [cell setContentInfo:dict];
     return  cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
     UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
     return  cell.frame.size.height;
}
这样写,在Cell赋值内容的时候,会根据内容设置布局,当然也就可以知道Cell的高度,想想如果1000行,那就会调用1000+页面Cell个数次tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法,而我们对Cell的处理操作,都是在这个方法里的!什么赋值、布局等等。开销自然很大,这种方案Pass。。。改进代码。

2. 直接计算每个cell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
     NSDictionary *dict = self.dataList[indexPath.row];
     return  [ContacterTableCell cellHeightOfInfo:dict];
}
3. 可以提前计算cell高度,直接显示获取
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
     NSDictionary *dict = self.dataList[indexPath.row];
CGRect rect = [dict[@ "frame" ] CGRectValue];
     return  rect.frame.height;
}
4. 当cell很复杂时,可以直接绘制cell
//异步绘制
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         CGRect rect = [_data[@ "frame" ] CGRectValue];
         UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);
         CGContextRef context = UIGraphicsGetCurrentContext();
//整个内容的背景
         [[UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1] set];
         CGContextFillRect(context, rect);
//转发内容的背景
         if  ([_data valueForKey:@ "subData" ]) {
             [[UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1] set];
             CGRect subFrame = [_data[@ "subData" ][@ "frame" ] CGRectValue];
             CGContextFillRect(context, subFrame);
             [[UIColor colorWithRed:200/255.0 green:200/255.0 blue:200/255.0 alpha:1] set];
             CGContextFillRect(context, CGRectMake(0, subFrame.origin.y, rect.size.width, .5));
         }
         
         {
     //名字
             float leftX = SIZE_GAP_LEFT+SIZE_AVATAR+SIZE_GAP_BIG;
             float x = leftX;
             float y = (SIZE_AVATAR-(SIZE_FONT_NAME+SIZE_FONT_SUBTITLE+6))/2-2+SIZE_GAP_TOP+SIZE_GAP_SMALL-5;
             [_data[@ "name" ] drawInContext:context withPosition:CGPointMake(x, y) andFont:FontWithSize(SIZE_FONT_NAME)
                              andTextColor:[UIColor colorWithRed:106/255.0 green:140/255.0 blue:181/255.0 alpha:1]
                                 andHeight:rect.size.height];
     //时间+设备
             y += SIZE_FONT_NAME+5;
             float fromX = leftX;
             float size = [UIScreen screenWidth]-leftX;
             NSString *from = [NSString stringWithFormat:@ "%@  %@" , _data[@ "time" ], _data[@ "from" ]];
             [from drawInContext:context withPosition:CGPointMake(fromX, y) andFont:FontWithSize(SIZE_FONT_SUBTITLE)
                    andTextColor:[UIColor colorWithRed:178/255.0 green:178/255.0 blue:178/255.0 alpha:1]
                       andHeight:rect.size.height andWidth:size];
         }
//将绘制的内容以图片的形式返回,并调主线程显示
UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();
         UIGraphicsEndImageContext();
         dispatch_async(dispatch_get_main_queue(), ^{
             if  (flag==drawColorFlag) {
                 postBGView.frame = rect;
                 postBGView.image = nil;
                 postBGView.image = temp;
             }
}
//内容如果是图文混排,就添加View,用CoreText绘制
[self drawText];
}}


UITableView的优化主要从三个方面入手:

  • 提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法;

  • 异步绘制,遇到复杂界面,遇到性能瓶颈时,可能就是突破口;

  • 滑动时按需加载,这个在大量图片展示,网络加载的时候很管用!(SDWebImage已经实现异步加载,配合这条性能杠杠的)。

除了上面最主要的三个方面外,还有很多几乎大伙都很熟知的优化点:

  • 正确使用reuseIdentifier来重用Cells

  • 尽量使所有的view opaque,包括Cell自身

  • 尽量少用或不用透明图层

  • 如果Cell内现实的内容来自web,使用异步加载,缓存请求结果

  • 减少subviews的数量

  • 在heightForRowAtIndexPath:中尽量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后缓存结果

  • 尽量少用addView给Cell动态添加View,可以初始化时就添加,然后通过hide来控制是否显示



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值