美文网首页
iOS Rendering 三: iOS中的渲染架构

iOS Rendering 三: iOS中的渲染架构

作者: iOS_修心 | 来源:发表于2022-05-25 18:43 被阅读0次

各个渲染框架

UIKit、SwiftUI、Core Animation、Core Graphics、Core Image、OpenGL ES、Metal。


UIKit:日常开发最常用的UI框架,可以通过设置UIKit组件的布局以及相关属性来绘制界面。其实本身UIView并不拥有屏幕成像的能力,而是View上的CALayer属性拥有展示能力。(UIView继承自UIResponder,其主要负责用户操作的事件响应,iOS事件响应传递就是经过视图树遍历实现的。)

SwiftUI:苹果在WWDC-2019推出的一款全新的“声明式UI”框架,使用Swift编写。一套代码,即可完成iOS、iPadOS、macOS、watchOS的开发与适配。

Core Animation:核心动画,一个复合引擎。尽可能快速的组合屏幕上不同的可视内容。分解成独立的图层(CALayer),存储在图层树中。

Core Graphics:基于 Quartz 高级绘图引擎,主要用于运行时绘制图像。比如 CGRect 就定义在这个框架下

Core Image:运行前图像绘制,对已存在的图像进行高效处理。

GPU Driver:上述软件框架相互之间也有着依赖关系,不过所有框架最终都会通过 OpenGL 连接到 GPU Driver,GPU Driver 是直接和 GPU 交流的代码块,直接与 GPU 连接。

OpenGL ES:OpenGL for Embedded Systems,简称 GLES,是 OpenGL 的子集。由GPU厂商定制实现,可通过C/C++编程操控GPU

Metal:由苹果公司实现,WWDC-2018已经推出Metal2,渲染性能比OpenGL ES高。为了解决OpenGL ES不能充分发挥苹果芯片优势的问题。 Core Animation、Core Image、SceneKit、SpriteKit 等渲染框架都是构建于 Metal 之上的。

Core Animation 是什么

Core Animation,它本质上可以理解为一个复合引擎,主要职责包含:渲染、构建和实现动画
Core AnimationAppKitUIKit 完美的底层支持,同时也被整合进入 CocoaCocoa Touch 的工作流之中,它是 app 界面渲染和构建的最基础架构。 Core Animation 的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容是被分解成独立的 layer(iOS 中具体而言就是 CALayer),并且被存储为树状层级结构。这个树也形成了 UIKit 以及在 iOS 应用程序当中你所能在屏幕上看见的一切的基础。

UIView和CALayer关系

CALayer 是显示的基础:存储 bitmap

简单理解,CALayer 就是屏幕显示的基础。那 CALayer 是如何完成的呢?让我们来从源码向下探索一下,在 CALayer.h 中,CALayer 有这样一个属性 contents:

/** Layer content properties and methods. **/

/* An object providing the contents of the layer, typically a CGImageRef,
 * but may be something else. (For example, NSImage objects are
 * supported on Mac OS X 10.6 and later.) Default value is nil.
 * Animatable. */

@property(nullable, strong) id contents;

An object providing the contents of the layer, typically a CGImageRef.

contents 提供了 layer 的内容,是一个指针类型,在 iOS 中的类型就是 CGImageRef(在 OS X 中还可以是 NSImage)。而我们进一步查到,Apple 对 CGImageRef 的定义是:

A bitmap image or image mask.

看到 bitmap,这下我们就可以和之前讲的的渲染流水线联系起来了:实际上,CALayer 中的 contents 属性保存了由设备渲染流水线渲染好的位图 bitmap(通常也被称为 backing store),而当设备屏幕进行刷新时,会从 CALayer 中读取生成好的 bitmap,进而呈现到屏幕上。
所以,如果我们在代码中对 CALayer 的 contents 属性进行了设置,比如这样:

// 注意 CGImage 和 CGImageRef 的关系:
// typedef struct CGImage CGImageRef;
layer.contents = (__bridge id)image.CGImage;

那么在运行时,操作系统会调用底层的接口,将 image 通过 CPU+GPU 的渲染流水线渲染得到对应的 bitmap,存储于 CALayer.contents 中,在设备屏幕进行刷新的时候就会读取 bitmap 在屏幕上呈现。
也正因为每次要被渲染的内容是被静态的存储起来的,所以每次渲染时,Core Animation 会触发调用 drawRect: 方法,使用存储好的 bitmap 进行新一轮的展示。

UIView

UIView - Apple
Views are the fundamental building blocks of your app's user interface, and the UIView class defines the behaviors that are common to all views. A view object renders content within its bounds rectangle and handles any interactions with that content.

根据 Apple 的官方文档,UIView 是 app 中的基本组成结构,定义了一些统一的规范。它会负责内容的渲染以及,处理交互事件。具体而言,它负责的事情可以归为下面三类

  • Drawing and animation:绘制与动画
  • Layout and subview management:布局与子 view 的管理
  • Event handling:点击事件处理

两者关系

  • 每个 UIView 内部都有一个 CALayer 在背后提供内容的绘制和显示,并且 UIView 的尺寸样式都由内部的 Layer 所提供。两者都有树状层级结构,layer 内部有 SubLayers,View 内部有 SubViews.但是 Layer 比 View 多了个AnchorPoint

  • 在 View显示的时候,UIView 做为 Layer 的 CALayerDelegate,View 的显示内容由内部的 CALayer 的 display

  • CALayer 是默认修改属性支持隐式动画的,在给 UIView 的 Layer 做动画的时候,View 作为 Layer 的代理,Layer 通过 actionForLayer:forKey:向 View请求相应的 action(动画行为)

  • layer 内部维护着三分 layer tree,分别是 presentLayer Tree(动画树),modeLayer Tree(模型树), Render Tree (渲染树),在做 iOS动画的时候,我们修改动画的属性,在动画的其实是 Layer 的 presentLayer的属性值,而最终展示在界面上的其实是提供 View的modelLayer

两者主要的关系如下:

  1. CALayer 是 UIView 的属性之一,负责渲染和动画,提供可视内容的呈现。
  2. UIView 提供了对 CALayer 部分功能的封装,同时也另外负责了交互事件的处理。

两者主要的异同点如下:

相同的层级结构:我们对 UIView 的层级结构非常熟悉,由于每个 UIView 都对应 CALayer 负责页面的绘制,所以 CALayer 也具有相应的层级结构。

部分效果的设置:因为 UIView 只对 CALayer 的部分功能进行了封装,而另一部分如圆角、阴影、边框等特效都需要通过调用 layer 属性来设置。

是否响应点击事件:CALayer 不负责点击事件,所以不响应点击事件,而 UIView 会响应。

不同继承关系:CALayer 继承自 NSObject,UIView 由于要负责交互事件,所以继承自 UIResponder

当然还剩最后一个问题,为什么要将 CALayer 独立出来,直接使用 UIView 统一管理不行吗?为什么不用一个统一的对象来处理所有事情呢?

这样设计的主要原因就是为了职责分离,拆分功能,方便代码的复用。
通过 Core Animation 框架来负责可视内容的呈现,这样在 iOS 和 OS X 上都可以使用 Core Animation 进行渲染。与此同时,两个系统还可以根据交互规则的不同来进一步封装统一的控件,比如 iOS 有 UIKit 和 UIView,OS X 则是AppKit 和 NSView。

相关文章

网友评论

      本文标题:iOS Rendering 三: iOS中的渲染架构

      本文链接:https://www.haomeiwen.com/subject/xvxyprtx.html