美文网首页iOS学习
Instruments的Core Animation进行性能优化

Instruments的Core Animation进行性能优化

作者: Maj_sunshine | 来源:发表于2018-08-02 17:40 被阅读61次

    我们可以通过打开product->profile->Core Animation我们可以对app的进行一些优化。

    • 我们可以查看Core Animation的功能选项(九项)


      屏幕快照 2018-07-31 下午4.39.00.png

    功能介绍

    Color Blended Layers(图层混合)

    • 如果视图中的颜色混合越多,那么GPU通过混合纹理计算出像素的RGB值需要消耗的时间就越长,GPU的使用率就越高,可以通过减少颜色混合来提升滑动的流畅性.

    • 造成图层混合的原因
      1 控件透明度alpha不为1
      2 背景颜色backgroundColor不能为[UIColor clearColor]
      3 view的opaque为NO。(我也对这个属性摸不准,希望懂得人能告诉我)

    • 调试选项"Color Blended Layers"检测图层混合,发生图层混合的会变红色,没有的则显示为绿色。

    Color Hits Green and MissesRed(光栅化)

    • 光栅化是将一个layer预先渲染成位图(bitmap),然后加入缓存中。如果对于阴影效果这样比较消耗资源的静态内容进行缓存,可以得到一定幅度的性能提升。
    // 将layer光栅化
    label.layer.shouldRasterize = true
    

    调试选项“Color Hits Green and Misses Red”,缓存命中为绿色,否则显示为红色。

    Color Copied Images
    • 检查我们有无使用不正确图片格式,若是GPU不支持的色彩格式的图片则会标记为青色
    • 让UI和服务器给图的时候尽量给PNG格式的图片,至少我们项目中都是用的PNG。
    Color Non-Standard Surface Formats (不标准的表面颜色格式)

    打开这个选项,几乎Label和Button的titleLabel的背景颜色都会出现银白色,打开微信和简书的app也发现这个存在。

    Color Immediately(颜色刷新频率)

    使用此选项加快颜色刷新的频率。不过我们一般不用。

    Color Misaligned Images(图片大小)

    检查了图片是否被放缩,像素是否对齐。被缩放的图片会被标记为黄色,像素不对齐则会标注为紫色。这个在项目中也是经常出现。

    Color Offscreen-Rendered Yellow(离屏渲染)

    离屏渲染会先在屏幕外创建新缓冲区,离屏渲染结束后,再从离屏切到当前屏幕, 把离屏的渲染结果显示到当前屏幕上,这个上下文切换的过程是非常消耗性能的,实际开发中尽可能避免离屏渲染。

    触发离屏渲染的行为

    (1)drawRect:方法
    (2)layer.shadow
    (3)layer.allowsGroupOpacity or layer.allowsEdgeAntialiasing
    (4)layer.shouldRasterize(光栅化)
    (5)layer.mask
    (6)layer.masksToBounds && layer.cornerRadius
    
    • 在项目开发中drawRect方法实际对性能损耗有点大,会造成CPU的使用率暴涨。我们能用CAShapeLayer替代的不去调用drawRect方法。
    • 用ShadowPath来替代shadowOffset绘制阴影,ShadowPath绘制不会造成离屏渲染。
    • layer.allowsGroupOpacity :子 layer 在视觉上的透明度的上限是其父 layer 的 opacity,为什么要开启这个,自己写的layer透明度自己没有b数么。
    • layer.allowsEdgeAntialiasing抗锯齿,如果你的layer被你缩放旋转造成出现锯齿,那么可以用这个属性,没办法。
    • layer.shouldRasterize开启光栅化会造成离屏渲染,所以在实际开发中我们要少用这个属性。
    • layer.mask,能不用就不用吧
    • layer.masksToBounds && layer.cornerRadius切圆角的方法有很多种,不要说只有这一种。
    Color Compositing Fast-Path Blue(快速路径)

    这个选项勾选后,由OpenGL compositor进行绘制的图层会标记为蓝色

    • Flash Updated Regoins
      这个选项会对重绘的内容高亮成黄色,重绘就是指使用Core Graphics绘制,绘制会损耗一定的性能,因此重绘区域应该越小越好。

    开始优化

    图层混合

    图层混合2.png

    我们可以看出很多图片和label造成了图层的混合


    label的图层混合原因
    • 默认的backgroundColor为nil.是个透明的样式。
    @property(nullable, nonatomic,copy)            UIColor          *backgroundColor UI_APPEARANCE_SELECTOR; 
    // default is nil. Can be useful with the appearance proxy on custom UIView subclasses.
    

    如果没有给label添加一个backgroundColor,肯定会产生图层混合。

    • label的内容是中文,label实际渲染区域要大于label的size,最外层多了一个sublayer。
      所以需要给label添加
    // masksToBounds默认为NO
    label.layer.masksToBounds = YES;
    

    我觉得我这个项目中的label都可以设置label.layer.masksToBounds,所以说干就干

    • 因为UIView的clipsToBounds属性没有关键字UI_APPEARANCE_SELECTOR,所以不能全局去设置裁剪。只有遵循UIAppearance的类并且设置UI_APPEARANCE_SELECTOR的属性才能去全局设置样式。

    • 用methodSwizzle来注入masksToBounds代码。

    + (void)load {
        Class class = [self class];
        // 取得函数名称
        SEL originSel = @selector(setText:);
        SEL swizzleSel = @selector(swizzleSetText:);
    
        Method originMethod = class_getInstanceMethod(class, originSel);
        Method swizzleMethod = class_getInstanceMethod(class, swizzleSel);
    
        BOOL addMethod = class_addMethod(class, originSel, method_getImplementation(swizzleMethod),method_getTypeEncoding(swizzleMethod));
        if (addMethod) {
            class_replaceMethod(class, swizzleSel, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
        } else {
            method_exchangeImplementations(originMethod, swizzleMethod);
        }
    }
    
    - (void)swizzleSetText:(NSString *)text {
        [self swizzleSetText:text];
        self.layer.masksToBounds = YES;
    }
    
    • backgroundColor背景颜色的设置,这个属性系统设置了UI_APPEARANCE_SELECTOR标识,所以我们可以全局设置,但是自身项目中可能会导致颜色重叠,所以我在需要去除图层混合的地方添加
    // 一般白色
    label.backgroundColor = [UIColor whiteColor];
    

    image的图层混合

    我发现UIGraphicsBeginImageContextWithOptions(<#CGSize size#>, <#BOOL opaque#>, <#CGFloat scale#>)的第二个参数,isOpaque 是用来决定透明通道是否被渲染。对没有透明度的图片设置这个参数为false,可能导致图片有粉红色调。

    我用下面方法来切圆角,并解决图层混合

    /**
     切圆角并解决图层混合
     
     @param fillColor 填充颜色
     @param cornerRadius 半径
     @param size 大小
     @return <#return value description#>
     */
    
    - (UIImage *)imageRoundCornerWithFillColor:(UIColor *)fillColor cornerRadius:(CGFloat)cornerRadius size:(CGSize)size {
        // 设置为YES,解决离屏渲染解决的情况下,存在的图层混合
        if([[UIScreen mainScreen] scale] == 2.0){      // @2x
            UIGraphicsBeginImageContextWithOptions(size, YES, 2.0);
        }else if([[UIScreen mainScreen] scale] == 3.0){ // @3x ( iPhone 6plus 、iPhone 6s plus)
            UIGraphicsBeginImageContextWithOptions(size, YES, 3.0);
        }else{
            UIGraphicsBeginImageContext(size);
        }
        
        CGRect bounds = CGRectMake(0, 0, size.width, size.height);
        // UIGraphicsBeginImageContextWithOptions的opaque设置为YES后导致的四边黑色。
        [fillColor setFill];
        UIRectFill(bounds);
        
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:cornerRadius];
        [path addClip];
        [self drawInRect:bounds];
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    
    图层混合处理后 图层混合处理后.png

    Color Non-Standard Surface Formats(不标准的表面颜色格式)

    不标准的表面颜色格式.png
    通过上面的图层混合解决处理后,Color Non-Standard Surface Formats的灰色区域也会随之去除。

    Color Misaligned Images(图片大小)

    图片Color Misaligned Images优化前.gif

    上面是优化前出现的缩放的图片会被标记为黄色,像素不对齐则会标注为紫色。主要文字label或button也会出现像素不对齐的情况。

    • 网络图片被缩放很正常,我们要做的是尽量减少缩放和像素不对齐情况的发生。
      像素不对齐是指:视图或图片的点数(point),不能换算成整数的像素值(pixel),导致显示视图的时候需要对没对齐的边缘进行额外混合计算,影响性能。所有frame的取值尽量为证书,避免不必要的计算。
      图片标记为黄色的原因主要为:图片大小不对的造成的缩放
    1. 像素不对齐,利用ceilf()向上取整。防止frame为小数导致的性能损耗。
    2. tableView中头尾视图高度不能取值0.01,如果不需要就给个最小值CGFLOAT_MIN
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    return CGFLOAT_MIN; 
    } 
    

    3 图片缩放(记得先解决图片像素不对齐的问题,如果有的话),再用上面的- (UIImage *)imageRoundCornerWithFillColor:(UIColor *)fillColor cornerRadius:(CGFloat)cornerRadius size:(CGSize)size方法去获取赋值(注意这个方法的图片相当于自适应填充)

    优化后.png
    • 优化后,那个箭头为黄色表示图片被缩放了,这是我的本地图片,我只要调整大小正确就会正常。

    相关文章

      网友评论

        本文标题:Instruments的Core Animation进行性能优化

        本文链接:https://www.haomeiwen.com/subject/xgrhvftx.html