当调用UIView的setNeedsDisplay
方法时,会调用CALayer的同名方法setNeedsDisplay
,这时并没有立即发生绘制,而只是相当于在当前layer打上了脏标记, 会在Runloop即将结束时才会调用[CALayer display]
,而这个方法的内部会判断是否实现了displayLayer这个方法,如果没有实现,那么走系统调用,如果实现了,就为我们异步绘制提供了入口。
系统绘制实现
image.png异步绘制实现
通过实现layer的代理方法displayLayer
- 代理负责生成对应的bitmap
-
设置该bitmap作为layer.contents属性的值
image.png
例:
- (void)displayLayer:(CALayer *)layer {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
__block CGSize size;
dispatch_sync(dispatch_get_main_queue(), ^{
size = self.bounds.size;
});
UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
[self draw:context size:size];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
layer.contents = (__bridge id)image.CGImage;
});
});
}
问题
在UIView的dreaw方法里绘图,与在CALayer图层代理中绘制的区别:
drawRect:方法是由UIKit组件进行调用,因此里面可以使用一些UIKit封装的方法进行绘图,而直接绘制到图层的方法由于并非UIKit直接调用因此只能用原生的Core Graphics方法绘制。
CALayer图层内部绘图有两个方法:(都需要调用setNeedDisplay方法)
通过图层代理绘制 (CALayerDelegate)
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
通过自定义图层绘制 (CALayer) - (void)drawInContext:(CGContextRef)ctx;
所以有三种绘制方式
- 直接在UIView上绘制(draw方法中)
- 通过图层代理绘制 (CALayerDelegate)
- 通过自定义图层绘制 (重写CALayer的drawInContext方法)
网友评论