-
内存暴增
以加载一张7033 × 10110的图片为例,解压缩生成的bitmap可高达7033101104/1024/1024 = 271M。
如果直接用UIKit-setImage方法对ImageView.image赋值,app占用内存会由60多MB激增到323MB。 -
CATiledLayer
CATiledLayer是继承于CALayer的方片图层,可以利用其对图片进行分片绘制。
@interface LargeImageView(){
UIImage *originImage;
CGFloat imageScale;
}
@end
@implementation LargeImageView
- (void)setImage:(UIImage *)image {
originImage = image;
[self setBackgroundColor:[UIColor whiteColor]];
imageScale = self.frame.size.width/image.size.width;
int lev = ceil(log2(1/imageScale))+1;
CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
tiledLayer.levelsOfDetail = 1;
tiledLayer.levelsOfDetailBias = lev;
}
+ (Class)layerClass {
return [CATiledLayer class];
}
- (void)drawRect:(CGRect)rect {
@autoreleasepool{
CGRect imageCutRect = CGRectMake(rect.origin.x / imageScale,
rect.origin.y / imageScale,
rect.size.width / imageScale,
rect.size.height / imageScale);
CGImageRef imageRef = CGImageCreateWithImageInRect(originImage.CGImage, imageCutRect);
UIImage *tileImage = [UIImage imageWithCGImage:imageRef];
CGContextRef context = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(context);
[tileImage drawInRect:rect];
CGImageRelease(imageRef);
UIGraphicsPopContext();
}
}
@end
加载效果:
CATiledLayer背后采用了多线程对图片进行绘制,cpu使用率会明显提升,逐个区域绘图也降低了内存峰值。
CATiledLayer主要属性:
tileSize:在绘制视图层时,将View分割成最大不超过tileSize指定的尺寸,然后调用drawRect方法逐个区域绘制。默认是{256 , 256}
以一张尺寸7033 × 10110的图片为例。
设置tilesize为{7033 , 10110},其实相当于整张图片加载,跟不使用TiledLayer差不多,内存峰值可达235MB。
设置tilesize为{500 , 500},内存峰值明显下降了不少,即72.4MB。
设置tilesize为{200 , 200},内存峰值会下降到66.7MB
CATiledLayer可以进行逐个区域绘制,明显减少内存的占用,缓解了内存压力。
levelsOfDetail:缩小图片时的层级数量,即图片可以缩小到最大缩小级别,每一级是上一级的 1/2。
levelsOfDetailBias:放大图片时的层级数量,即图片可以缩小到最大放大级别,每一级是上一级的 2倍。
CATiledLayer可以配合UIScrollView来进行图片的缩放。
levelsOfDetailBias 不指定的话,设置levelsOfDetail=n,则CATiledLayer 将会在 UIScrollView 的 zoomScale 为以下数字时进行重绘:2^-1 -> 2^-2 -> … -> 2^-n。也就是 1/2, 1/4, 1/8, 1/16, … , 1/2^n。
所以,在levelsOfDetailBias 不指定的话,zoomScale大于0.5就不再重绘图片,图片也会变得越来越模糊。
因此就需要对levelsOfDetailBias进行设置,当设置levelsOfDetailBias=m,levelsOfDetail=n,则CATiledLayer 将会在 UIScrollView 的 zoomScale 为以下数字时进行重绘: 2^m * 2^-1 -> 2^m * 2^-2 -> … -> 2^m * 2^-n
即: 2^(m – 1) -> 2^(m – 2) -> 2^(m – 3) ->… -> 2^(m – n)
可简单理解成:
levelsOfDetail表示一共有多少个drawLayer的位置
levelsOfDetailBias表示比1大的位置里有多少个drawLayer的位置(包括1)