- 以前闲时用instruments的Time profiler调试过APP,发现用tableView: cellForRowAtIndexPath: 中cell的图片设置耗时较多,之前改了一下,如下
dispatch_async(dispatch_get_global_queue(0, 0), ^{
UIImage *cellImage = [UIImage imageNamed: self.imageNamesArray[indexPath.row] ];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = cellImage;
});
});
发现没什么效果,就没去改了(这就是不求甚解,?),直到最近被人问到图片的显示流程,去网上搜索相关资料,才发现用imageNamed的这种方式创建的图片,并不会立即解码,而是发生在CALayerPrepareCommit后 提交到GPU之前,才会去解码,那样总是会在主线程解码的,参考图片网址,参考YYKit大神写的文章
后来在GitHub上面搜到了一种解决方案,就是在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap中直接创建图片,UIImage+ImmediateDecode.m中主要代码如下
+ (instancetype)imageWithName:(NSString*)name{
NSString *imgPath = [[NSBundle mainBundle] pathForResource:name ofType:nil];
if ( !imgPath ) {
imgPath = [[NSBundle mainBundle] pathForResource:name ofType:@"png"];
}
if (!imgPath) {
imgPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@@2x" ,name] ofType:@"png"];
}
if (!imgPath) {
imgPath = [[NSBundle mainBundle] pathForResource:name ofType:@"jpg"];
}
return [UIImage initImmediateLoadWithContentsOfFile: imgPath];
}
+ (UIImage*) initImmediateLoadWithContentsOfFile:(NSString*)path {
UIImage *image = [[UIImage alloc] initWithContentsOfFile:path];
CGImageRef imageRef = [image CGImage];
CGRect rect = CGRectMake(0.f, 0.f, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
CGContextRef bitmapContext = CGBitmapContextCreate(NULL,
rect.size.width,
rect.size.height,
CGImageGetBitsPerComponent(imageRef),
CGImageGetBytesPerRow(imageRef),
CGImageGetColorSpace(imageRef),
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
);
//kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little are the bit flags required so that the main thread doesn't have any conversions to do.
CGContextDrawImage(bitmapContext, rect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(bitmapContext);
UIImage* decompressedImage = [[UIImage alloc] initWithCGImage: decompressedImageRef scale:2.0 orientation:UIImageOrientationUp];
CGImageRelease(decompressedImageRef);
CGContextRelease(bitmapContext);
return decompressedImage;
}
tableView: cellForRowAtIndexPath: 中的代码改为如下
dispatch_async(dispatch_get_global_queue(0, 0), ^{
UIImage *tempImage = [UIImage imageWithName:self.imageNamesArray[indexPath.row]];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = tempImage;
[cell setNeedsLayout];
[cell layoutIfNeeded];
});
});
- Tips:
- imageNamed:的方式对图片名称要求比较松,可以自动识别2x、3x的图片,以及png不带后缀都可以;但是以[[NSBundle mainBundle] pathForResource:@"myCamera" ofType:@"png”] 如果图片是myCamera@2x的话,则获取的路径为空
- Instruments 底部的call tree 设置一般勾选第2、3、4项;call tree constraints 可以设置最小的耗时操作如16ms
- Instruments 鼠标框选时间轴中的某部分可以只看选中区域的耗时操作;Option + Click 智能展开或折叠call tree