性能优化一

一、图像性能优化

1、减少view个数 ,例如聊天的图文混排,使用富文本代替labels,imageviews。
2、减少使用半透明效果,或者不要把半透明加在一个经常变化的view之上,因为,不仅底层view要更新,半透明的也要更新。
3、 shouldRasterize(栅格化) == true,将当前view绘制成image缓存,这个绘制过程本身比较耗时耗内存,但是如果界面很少变化,这种缓存能提升性能。栅格化就是将内容转化成图片。

二、图像性能检测,Core Animation工具

1 Blended像素混合

1.1 当图层有半透明时,如:view.backgroundcolor。

GPU需要进行像素混合,需要先绘制透明层下层的内容,再叠加透明层以达到透明的效果,而不影响帧率的情况下,GPU可绘制的像素是有限制的。

1.2 通常优化方式

  • backgroundColor设置为不透明色
  • Opaque设置为YES
  • 图片能不用透明的切图成不透明
    例1:运行结果见图一。
- (void)testBlendedLayer
{
    __block CGFloat width = 200;
    __block CGFloat leftOffset = (SCREEN_WIDTH - 200)/2.0;
    __block CGFloat topOffset = 70;
    [self testBlendedLayer:^(UILabel *label) {
        label.frame = CGRectMake(leftOffset, topOffset, width, 30);
        topOffset += 50;
        label.text = @"背景颜色:默认";
    }];

    [self testBlendedLayer:^(UILabel *label) {
        label.frame = CGRectMake(leftOffset, topOffset, width, 30);
        topOffset += 50;
        
        label.text = @"背景颜色:半透明";
        label.backgroundColor = [UIColor colorWithWhite:0 alpha:0.3];
    }];
    
    [self testBlendedLayer:^(UILabel *label) {
        label.frame = CGRectMake(leftOffset, topOffset, width, 30);
        topOffset += 50;
        
        label.text = @"背景颜色:不透明";
        label.backgroundColor = [UIColor lightGrayColor];
    }];

    [self testBlendedLayer:^(UILabel *label) {
        label.frame = CGRectMake(leftOffset, topOffset, width, 30);
        topOffset += 50;
        
        label.text = @"背景颜色:无混合情况";
        label.backgroundColor = [UIColor lightGrayColor];
        label.layer.masksToBounds = YES;
    }];
}

- (void)testBlendedLayer:(void (^) (UILabel *label))construct
{
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
    label.textColor = [UIColor blackColor];
    if (construct) {
        construct(label);
    }
    [self.view addSubview:label];
}
图一 像素混合.jpeg

1:55:47

2、Color Copied images 图片能否需CPU要转码,需要的显示蓝色,如图二所示。

- (void)viewDidLoad {
    UIImageView *imageView = [[UIImageView alloc]  initWithFrame:self.view.bounds];
    UIImage *origin = [UIImage imageNamed:@"16.png"];
    UIImage *image = [Util decodeImage:origin toSize:imageView.layer.bounds.size];
    imageView.image = origin;
    imageView.opaque = YES;

    [self.view addSubview:imageView];
    [super viewDidLoad];
}

+ (UIImage *)decodeImage:(UIImage *)image toSize:(CGSize)size
{
    if (image == nil) { // Prevent "CGBitmapContextCreateImage: invalid context 0x0" error
        return nil;
    }
    
    @autoreleasepool{
        // do not decode animated images
        if (image.images != nil) {
            return image;
        }
        
        CGImageRef imageRef = image.CGImage;
        
        CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
        BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
                         alpha == kCGImageAlphaLast ||
                         alpha == kCGImageAlphaPremultipliedFirst ||
                         alpha == kCGImageAlphaPremultipliedLast);
        if (anyAlpha) {
            NSLog(@"图片解压失败,存在alpha通道");
            return image;
        }
        
        // current
        CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(imageRef));
        CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(imageRef);
        
        BOOL unsupportedColorSpace = (imageColorSpaceModel == kCGColorSpaceModelUnknown ||
                                      imageColorSpaceModel == kCGColorSpaceModelMonochrome ||
                                      imageColorSpaceModel == kCGColorSpaceModelCMYK ||
                                      imageColorSpaceModel == kCGColorSpaceModelIndexed);
        if (unsupportedColorSpace) {
            colorspaceRef = CGColorSpaceCreateDeviceRGB();
        }
        CGFloat scale = [UIScreen mainScreen].scale;
        size_t width = size.width;
        size_t height = size.height;
        NSUInteger bytesPerPixel = 4;
        NSUInteger bytesPerRow = bytesPerPixel * width;
        NSUInteger bitsPerComponent = 8;
        
        
        // kCGImageAlphaNone is not supported in CGBitmapContextCreate.
        // Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast
        // to create bitmap graphics contexts without alpha info.
        CGContextRef context = CGBitmapContextCreate(NULL,
                                                     width,
                                                     height,
                                                     bitsPerComponent,
                                                     bytesPerRow,
                                                     colorspaceRef,
                                                     kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);
        
        // Draw the image into the context and retrieve the new bitmap image without alpha
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
        CGImageRef imageRefWithoutAlpha = CGBitmapContextCreateImage(context);
        UIImage *imageWithoutAlpha = [UIImage imageWithCGImage:imageRefWithoutAlpha
                                                         scale:scale
                                                   orientation:image.imageOrientation];
        
        if (unsupportedColorSpace) {
            CGColorSpaceRelease(colorspaceRef);
        }
        
        CGContextRelease(context);
        CGImageRelease(imageRefWithoutAlpha);
        NSLog(@"图片解压成功");
        return imageWithoutAlpha;
    }

}

图二.png

3、Offscreen-Rendered工具

  • 离屏渲染
    在使用圆角、阴影和遮罩等视图功能的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所有就需要在屏幕外的上下文中渲染,即离屏渲染。
    产生离屏渲染原因:
    shouldRasterize(光栅化)、masks(遮罩)、shadows(阴影)、edge antialiasing(抗锯齿)、group opacity(不透明)、复杂形状设置圆角、渐变
    见链接:https://www.cnblogs.com/fishbay/p/7576176.html

4、Color Hits Green and Misses Red 检测栅格化的效果,绿色最佳

栅格化命中显示绿色,没有命中显示红色。见图三cell.rasterizeLbl.layer.shouldRasterize = YES;

图三 栅格化截图.jpeg

当 shouldRasterize 设成 true 时,layer 被渲染成一个 bitmap,并缓存起来,等下次使用时不会再重新去渲染了。实现圆角本身就是在做颜色混合(blending),如果每次页面出来时都blending,消耗太大,这时shouldRasterize = yes,下次就只是简单的从渲染引擎的 cache 里读取那张 bitmap,节约系统资源。
额外收获:如果在滚动 tableView 时,每次都执行圆角设置,肯定会阻塞 UI,设置这个将会使滑动更加流畅。

你可能感兴趣的:(性能优化一)