UI绘制的过程
UI绘制原理的过程.png当调用[UIView setNeedsDisplay]
方法时,系统会立即调用对应的layer的setNeedsDisplay
,之后给layer打上标记,在一次RunLoop将要结束时,会调用[CALayer display]
方法,然后进入到真正的绘制过程当中。
[CALayer display]
方法内部实现中,会判断有没有layer的delegate响应了displayLayer
方法,如果没有会执行系统绘制流程,如果响应了就为我们提供了异步绘制的入口。
系统绘制流程
在CALayer内部会创建一个backing store(CGContextRef),然后layer会判断它是否有代理,如果没有代理的话,会调用[CALayer drawInContext:]
, 如果有代理,会调用[layer.delegate drawLayer: inContext]
,然后做当前视图的绘制工作,这部分是发生在系统内部的,然后在一个合适的时机给予我们一个回调方法,就是[UIView drawRect:]
,[UIView drawRect:]
的默认实现是什么都不做,给我们开一个口子,就允许我们在系统绘制的基础上做一些其他的相关的绘制工作,最后不论是哪个分支,都是由CALayer上传对应的backing store(可以理解为位图)到GPU
异步绘制
[layer.delegate drawLayer:inContext:]
方法实现就可以进入到异步绘制的流程
- 代理负责生产对应的bitmap
- 设置该bitmap作为layer.contents属性的值
异步绘制的机制和流程
异步绘制的机制和流程.png在调用setNeedsDisplay
方法之后,在当前RunLoop快要结束时,由系统调用视图所对应的CALayer的display方法,然后如果代理实现了displayLayer:
函数,会调用代理的displayLayer:
函数方法,然后会通过子线程的切换,在子线程中做位图的绘制,此时主线程可以做别的事。
在全局并发队列子线程中
- 通过
CGBitmapContextCreate()
函数来创建一个位图的上下文 - 通过CoreGraphics的相关api做当前UI空间的绘制工作
- 再通过
CGBitmapContextCreateImage()
函数来根据当前所绘制的上下文,生成一张CGImage图片 - 然后回到主队列中提交位图,设置给CALayer的contents属性,这样就完成了一个UI控件的异步绘制
网友评论