UITableView性能优化

// 提前计算并缓存好高度
// 滑动时按需加载, 防止卡顿 配合SDWebImage https://github.com/johnil/VVeboTableViewDemo
dispatch_async ( DISPATCH_QUEUE_PRIORITY_DEFAULT , ^{
    // 异步绘制
});
// 缓存一切可以缓存的
// 默认高度44 定高的cell最好指定高度, 减少不必要的计算
self . tabelView . rowHeight = 88 ;
// 减少视图数目
// 减少多余的绘制操作
// 不给cell动态添加subView 用hidden属性 控制显示/隐藏
// 网络请求, 图片加载 开启多线程
// willDisplayCell 可以将数据绑定放在cell显示出来之后再执行 以提高效率
// 缓存不便于重用的view (存model里)
// --------   自适应高度   --------
// 尽量提高计算效率, 已计算过的高度需要进行缓存, 没必要进行第二次运算
// 必须满足3个条件
// 1. cell.contentView 四边与内部元素有约束关系(Autolayout)
// 2. 指定estimatedRowHeight属性的默认值
self . tabelView . estimatedRowHeight = 44 ;
// 3. 指定rowHeight属性为 automatic dimension
self . tabelView . rowHeight = UITableViewAutomaticDimension ;

// --------   离屏渲染: 圆角/阴影   --------
// 离屏渲染: 圆角/阴影, 另外开辟渲染缓冲区, 消耗性能 (多: 缓冲区频繁合并 上下文频繁切换, 导致掉帧)
UIImageView *imgV = [[ UIImageView alloc ] initWithImage :[ UIImage imageNamed : @"placeholder" ]];
imgV. frame = CGRectMake ( 100 , 100 , 100 , 100 );
[ self . view addSubview :imgV];
// 优化方案1: (推荐使用) CAShapeLayer UIBezierPath 结合, 可设置单个圆角
UIBezierPath *maskPath = [ UIBezierPath bezierPathWithRoundedRect :imgV. bounds byRoundingCorners : UIRectCornerAllCorners cornerRadii :imgV. bounds . size ];
CAShapeLayer *maskLayer = [[ CAShapeLayer alloc ] init ];
// 设置大小
maskLayer. frame = imgV. bounds ;
// 设置图形样子
maskLayer. path = maskPath. CGPath ;
imgV. layer . mask = maskLayer;
// 说明: AShapeLayer动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言,其效率极高,能大大优化内存使用情况
// 优化方案2: 使用贝塞尔曲线UIBezierPath Core Graphics框架画出一个圆角
// 开始对imageView进行画图
UIGraphicsBeginImageContextWithOptions (imgV. bounds . size , NO , 1.0 );
// 使用 贝赛尔曲线 画出一个圆形图
[[ UIBezierPath bezierPathWithRoundedRect :imgV. bounds cornerRadius :imgV. frame . size . width ] addClip ];
[imgV drawRect :imgV. bounds ];
imgV. image = UIGraphicsGetImageFromCurrentImageContext ();
// 结束画图
UIGraphicsEndImageContext ();
// shadow shadowPath优化
imgV. layer . shadowColor = [ UIColor redColor ]. CGColor ;
imgV. layer . shadowOpacity = 0.8 ;
imgV. layer . shadowRadius = 2.0 ;
imgV. layer . shadowOffset = CGSizeMake ( 0 , 0 );
CGFloat width = 3 ;
CGRect imgFrame = imgV. bounds ;
CGRect shadowFrame = CGRectMake (imgFrame. origin . x - width, imgFrame. origin . y - width, imgFrame. size . width + 2 *width, imgFrame. size . height + 2 *width);
UIBezierPath *path = [ UIBezierPath bezierPathWithRect :shadowFrame];
imgV. layer . shadowPath = path. CGPath ;
// 使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)
// 设置layer的opaque(不透明)值为YES,减少复杂图层合成
// 尽量使用不包含透明(alpha)通道的图片资源
// 尽量设置layer的大小值为整形值

// --------   Core Animation工具检测离屏渲染   --------
// Xcode->Open Develeper Tools->Instruments

// 可以将数据绑定放在cell显示出来之后再执行 以提高效率
- ( void )tableView:( UITableView *)tableView willDisplayCell:( UITableViewCell *)cell forRowAtIndexPath:( NSIndexPath *)indexPath {
   
}

- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath {
    static NSString *cellIncdentify = @"Cell" ;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier :cellIncdentify];
    if (!cell) {
    cell = [[ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :cellIncdentify];
    }
    // tableView停止滑动的时候异步加载图片
    if (tableView. dragging == NO && tableView. decelerating == NO ) {
        // 开始异步加载图片
        NSArray *visiblePaths = [tableView indexPathsForVisibleRows ];
        for ( NSIndexPath * i ndexPath in visiblePaths) {
            // 获取dataSource里的对象, 并且判断加载完成是不需要再次异步加载
        }
    }
    return cell;
}

猜你喜欢

转载自blog.csdn.net/Margaret_MO/article/details/79717741
今日推荐