UI绘制原理

当调用UIView的setNeedsDisplay方法时,会调用CALayer的同名方法setNeedsDisplay,这时并没有立即发生绘制,而只是相当于在当前layer打上了脏标记, 会在Runloop即将结束时才会调用[CALayer display],而这个方法的内部会判断是否实现了displayLayer这个方法,如果没有实现,那么走系统调用,如果实现了,就为我们异步绘制提供了入口。

image.png

系统绘制实现

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;

所以有三种绘制方式

  1. 直接在UIView上绘制(draw方法中)
  2. 通过图层代理绘制 (CALayerDelegate)
  3. 通过自定义图层绘制 (重写CALayer的drawInContext方法)

你可能感兴趣的:(UI绘制原理)