iOS学习

Instruments的Core Animation进行性能优化

2018-08-02  本文已影响61人  Maj_sunshine

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

功能介绍

Color Blended Layers(图层混合)

Color Hits Green and MissesRed(光栅化)

// 将layer光栅化
label.layer.shouldRasterize = true

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

Color Copied Images
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
Color Compositing Fast-Path Blue(快速路径)

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

开始优化

图层混合

图层混合2.png

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


label的图层混合原因
@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,肯定会产生图层混合。

// masksToBounds默认为NO
label.layer.masksToBounds = YES;

我觉得我这个项目中的label都可以设置label.layer.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;
}
// 一般白色
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也会出现像素不对齐的情况。

  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
上一篇 下一篇

猜你喜欢

热点阅读