内容简介:事实上,
UIKit
是iOS开发最常用的框架,可以通过设置 UIKit
组件的布局以及相关属性来绘制界面。
事实上, UIKit
自身并不具备在屏幕成像的能力,其主要负责对用户操作事件的响应( UIView
继承自 UIResponder
),事件响应的传递大体是经过逐层的 视图树 遍历实现的。
Core Animation
Core Animation
源自于 Layer Kit
,动画只是 Core Animation
的冰山一角。 Core Animation
是一个复合引擎,其职责是 尽可能快地组合屏幕上不同的可视内容,这些可视内容可被分解成独立的图层(即CALayer),这些图层会被存储在一个叫做图层树的体系之中 。从本质上而言, CALayer
是用户所能在屏幕上看见的一切的基础。
Core Graphics
Core Graphics
基于 Quartz
高级绘图引擎,主要用于运行时绘制图像。开发者可以使用此框架来处理基于路径的绘图,转换,颜色管理,离屏渲染,图案,渐变和阴影,图像数据管理,图像创建和图像遮罩以及PDF文档创建,显示和分析。
当开发者需要在运行时创建图像时,可以使用 Core Graphics
去绘制。与之相对的是运行前创建图像,例如用Photoshop提前做好图片素材直接导入应用。相比之下,我们更需要 Core Graphics
去在运行时实时计算、绘制一系列图像帧来实现动画。
Core Image
Core Image
与 Core Graphics
恰恰相反, Core Graphics
用于在运行时创建图像,而 Core Image
用于处理运行前创建的图像。 Core Image
框架拥有一系列现成的图像过滤器,能对一寸照的图像进行高效的处理。
大部分情况下, Core Image
会在GPU中完成工作,如果GPU忙,会使用CPU进行处理。
OpenGL ES
OpenGL ES
是 OpenGL
的子集。在图形渲染原理一文中提到过 OpenGL
是一套第三方标准,函数的内部实现由对应的GPU厂商开发实现。
UIView与CALayer的关系
CALayer
事实上是用户所能在屏幕上看见的一切的基础。为什么 UIKit
中的视图能够呈现可视化内容,就是因为 UIKit
中的每一个UI视图控件其实内部都有一个关联的 CALayer
,即 backing layer
。
由于这种一一对应的关系,视图层级有用 视图树 的树形结构,对应 CALayer
层级也拥有 图层树 的树形结构。
其中,视图的职责是创建并管理图层,以确保当子视图在层级关系中添加或被移除时,其关联的图层在图层树中也有相同的操作,即保证视图树和图层树在结构上的一致性。
为什么iOS要基于UIView和CALayer提供两个平行的层级关系呢?
其原因在于要做 职责分离 ,这样也能避免很多重复代码。在iOS和Mac OSX两个平台上,事件和用户交互有很多地方的不同,基于多点触控的用户界面和基于鼠标键盘的交互有着本质的区别,这就是为什么iOS有 UIKit
和 UIView
,对应Mac OSX有 AppKit
和 NSView
的原因。它们在功能上很相似,但是在实现上有着显著的区别。
实际上,这里并不是两个层级关系,而是四个。每一个都扮演着不同的角色。除了 视图树 和 图层树 ,还有 呈现树 和 渲染树 。
CALayer
那么为什么 CALayer
可以呈现可视化内容呢?因为 CALayer
基本等同于一个 纹理 。纹理是GPU进行图像渲染的重要依据。
在图形渲染原理中提到纹理本质上就是一张图片,因此 CALayer
也包含一个 contents
属性指向一块缓存区,称为 backing store
,可以存放位图(Bitmap)。iOS中将该缓存区保存的图片称为 寄宿图 。
图形渲染流水线支持从顶点开始进行绘制(在流水线中,顶点会被处理生成纹理),也支持直接使用纹理(图片)进行渲染。相应地,在实际开发中,绘制界面也有两种方式: 一种是 手动绘制 ;另一种是 使用图片 。
对此,iOS中也有两种相应的实现方式:
- 使用图片: contents image
- 手动绘制: custom drawing
Contents Image
Contents Image
是指通过 CALayer
的 contents
属性来配置图片。然而, contents
属性的类型为 id
,在这种情况下,可以给 contents
属性赋予任何值,app仍可以编译通过。但是在实践中,如果 contents
的值不是 CGImage
,得到的图层将是空白的。
既然如此,为什么要将 contents
的属性类型定义为 id
而非 CGImage
。因为在Mac OS系统中,该属性对 CGImage
和 NSImage
类型的值都起作用,而在iOS系统中,该属性只对 CGImage
起作用。
本质上, contents
属性指向的一块缓存区域,称为 backing store
,可以存放bitmap数据。
Custom Drawing
Custom Drawing
是指使用 Core Graphics
直接绘制寄宿图。实际开发中,一般通过继承 UIView
并实现 -drawRect:
方法来自定义绘制。
虽然 -drawRect:
是一个 UIView
方法,但事实上都是底层的 CALayer
完成了重绘工作并保存了产生的图片。 下图所示为 drawRect:
绘制定义寄宿图的基本原理
-
UIView
有一个关联图层,即CALayer
。 -
CALayer
有一个可选的delegate
属性,实现了CALayerDelegate
协议。UIView
作为CALayer
的代理实现了CALayerDelegate
协议。 - 当需要重绘时,即调用
-drawRect:
,CALayer
请求其代理给予一个寄宿图来显示。 -
CALayer
首先会尝试调用-displayLayer:
方法,此时代理可以直接设置contents
属性。
- (void)displayLayer:(CALayer *)layer; 复制代码
- 如果代理没有实现
-displayLayer:
方法,CALayer
则会尝试调用-drawLayer:inContext:
方法。在调用该方法前,CALayer
会创建一个空的寄宿图(尺寸由bounds
和contentScale
决定)和一个Core Graphics
的绘制上下文,为绘制寄宿图做准备,作为ctx
参数传入。
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx; 复制代码
- 最后,有
Core Graphics
绘制生成的寄宿图会存入backing store
。
Core Animation 流水线
介绍一下 Core Animation
流水线的工作原理:
Render Server
进程。
App通过IPC将渲染任务及相关数据提交给 Render Server
。 Render Server
处理完数据后,再传递至GPU。最后由GPU调用iOS的图像设备进行显示。
Core Animation
流水线的详细过程如下:
- 首先,由app处理事件(Handle Events),如:用户点击操作,在此过程中app可能需要更新 视图树 ,相应地, 图层树 也会被更新。
- 其次,app通过CPU完成对显示内容的计算,如:视图的创建、布局计算、图片解码、文本绘制等。在完成对现实内容的计算之后,app对图层进行打包,并在下一次RunLoop时将其发送至
Render Server
,即完成了一次commit Transaction
操作。 -
Render Server
主要执行OpenGL、Core Graphics相关程序,并调用GPU。 - GPU则在物理层上完成了对图像的渲染。
- 最终,GPU通过
Frame Buffer
、视频控制器等相关部件,将图像显示在屏幕上。
对上述步骤进行串联,他们执行所消耗的时间圆圆超过16.67ms,因此为了满足对屏幕的60FPS刷新率的支持,需要将这些步骤进行分解,通过流水线的方式并行执行,如下图:
Commit Transaction
在 Core Animation
流水线中,app调用 Render Server
前的最后一步 Commit Transaction
其实可以细分为4个步骤:
Layout Display Prepare Commit
Layout
Layout
阶段主要进行视图构建,包括: LayoutSubviews
方法的重载, addSubview:
方法填充子视图等。
Display
Display
阶段主要进行视图绘制,这里仅仅是设置成像的图元数据。重载视图的 drawRect:
方法可以自定义 UIView
的显示,其原理是在 drawRect:
方法内部绘制寄宿图,该过程使用GPU和内存。
Prepare
Prepare
阶段属于附加步骤,一般处理图像的解码和转码等操作。
Commit
commit
阶段主要将图层进行打包,并将它们发送至 Render Server
。该过程会递归执行,因为图层和视图都是以树形结构存在。
动画渲染原理
iOS动画的渲染也是基于上述 Core Animation
流水线完成的。这里我们重点关注app与 Render Server
的执行流程。
日常开发中,如果不是特别的复杂动画,一般使用 UIView
Animation实现,iOS将其处理过程分为如下三部阶段:
animationWithDuration:animations: Layout,Display,Prepare,Commit Render Server
参考博客iOS图像渲染原理
以上所述就是小编给大家介绍的《iOS 渲染框架》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 3天学写mvvm框架[三]:浏览器端渲染
- 如何选择正确的后端渲染框架:Next, Nuxt, Nest?
- Next.js 6.0.0 发布,React 服务器端渲染框架
- Next.js 6.0.1 发布,React 应用的后端渲染框架
- Next.js 6.0.2 发布,React 应用的后端渲染框架
- Next.js 6.1.1 发布,React 应用的后端渲染框架
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
大型网站技术架构演进与性能优化
许令波 / 电子工业出版社 / 2018-6 / 79
《大型网站技术架构演进与性能优化》从一名亲历者的角度,阐述了一个网站在业务量飞速发展的过程中所遇到的技术转型等各种问题及解决思路。从技术发展上看,网站经历了Web应用系统从分布式、无线多端、中台到国际化的改造;在解决大流量问题的方向上,涉及了从端的优化到管道到服务端甚至到基础环境优化的各个层面。 《大型网站技术架构演进与性能优化》总结的宝贵经验教训可以帮助读者了解当网站遇到类似问题时,应如何......一起来看看 《大型网站技术架构演进与性能优化》 这本书的介绍吧!