CALayer & drawRect

7
视图和窗口架构 中指出:

视图与核心动画层一起处理视图内容的渲染和动画。UIKit 中的每个视图都由一个图层对象支持(通常是 CALayer 类的实例),该对象管理视图的后备存储并处理与视图相关的动画。

在 "视图绘制周期" 部分中进一步说明:

UIView 类使用按需绘制模型来呈现内容。当视图首次出现在屏幕上时,系统会要求其绘制其内容。 系统捕获此内容的快照 并将该快照用作视图的可视表示。

这是否意味着,视图中通过 drawRect 方法调用绘制的内容会被捕获为快照并保存在其后备核心动画层中?
如果不是,请问这个内容快照在哪里 "驻留"?
如果不是,这是否意味着 CALayer 用于渲染 "静态" 内容,即不经常更改的内容,而 drawRect 用于渲染经常更改的内容,例如游戏应用程序中的内容?
附言:
这些问题与任何特定的代码实现无关。
我只是想了解 ios 视图层架构。
3个回答

11
这是否意味着在视图的drawRect方法调用中绘制的内容会被捕获,并保存在其后备核心动画层中的快照中?
是的。所有的东西都在幕后使用图层。UIView的-drawRect将捕获你所绘制的内容,并(据我所知)设置为该视图的子层的内容。它甚至可能在主图层对象上执行此操作。这就是'snapshot'保存的地方。
如果不是这样,那么这是否意味着CALayer用于渲染“静态”内容,即不经常更改的内容,而drawRect用于渲染经常更改的内容,例如在游戏应用中?
内容更改的频率并不会影响选择。使用drawRect与手动创建CALayer之间的区别不大。这取决于您如何组织视图中的子元素,或者是否要创建没有UIView细节(例如CATextLayer)的低级可重用层对象。如果您有多个不同的子元素需要绘制,则可以将它们拆分成具有自己自定义绘制代码的不同层。如果只有一个简单的内容要绘制,则可以在单个drawRect实现中完成所有操作。
话虽如此,您确实需要注意每个层最终都将成为单独的GPU“元素”,因此减少您拥有的图层数或使用父层的shouldRasterize+rasterizationScale属性可能会有性能好处。这将对整个图层层次结构进行快照,并创建单个栅格化图像以进行渲染,而不是分别进行n次渲染。

1
这是否意味着,在视图的drawRect方法调用中绘制的内容被捕获并保存在其后备核心动画层中的快照中?
两个词:“实现细节”
如果不是,这是否意味着CALayer用于呈现“静态”内容,即不经常更改的内容,并且drawRect用于呈现经常更改的内容,例如在游戏应用程序中?
不完全是。图层非常擅长动画内容(正如框架名称Core Animation所暗示的那样)。 drawRect适用于高级绘图,但重绘每一帧可能太慢(显然取决于您正在绘制的内容)。
我没有在您的问题中看到the Core Animation Programming Guide的提及。这是一个学习有关视图层部分的更多信息的好地方。

图层很适合在相同绘制内容上进行动画处理,而drawRect则每次调用时都会重新绘制内容。 - Stefan Fachmann
1
图层在值之间进行插值也很好。例如,可以对背景颜色、位置、变换、边框宽度等进行动画处理。 - David Rönnqvist

0

每个UIView都有一个基础的CALayer(实际上是在屏幕上呈现的内容)。

CALayer只是一个位图(保存像素)。当您调用setNeedsDisplay来显示视图时,CALayer会被标记为需要重新绘制。在运行循环的末尾,在处理事件之后,将创建CGContextRef并调用drawRect委托。然后,您可以在创建的上下文中绘制内容,然后将其复制到位图中,并最终与其他图层合成以在屏幕上显示。

因此,“快照”确实存储在CALayer中。这只是一种优化,使得图层不必重新绘制自己,除非它们被标记为需要重新绘制(使用setNeedsDisplay)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接