6
votes

In View and Window Architecture is stated, quote:

Views work in conjunction with Core Animation layers to handle the rendering and animating of a view’s content. Every view in UIKit is backed by a layer object (usually an instance of the CALayer class), which manages the backing store for the view and handles view-related animations.

Farther in the "The View Drawing Cycle" section is stated:

The UIView class uses an on-demand drawing model for presenting content. When a view first appears on the screen, the system asks it to draw its content. The system captures a snapshot of this content and uses that snapshot as the view’s visual representation.

Does that mean, that the content drawn in a view in its drawRect method call, is captured in a snapshot in saved in its backing core animation layer?

If not, where do this content snapshot "reside"?

If not, does that mean that CALayer is used to render "static" content, content that doesn't change very often, and drawRect is used to render content that changes often, for example in a game app?

p.s.

The questions are not related to any particular code implementation.

I just want to understand the ios view-layer architecture.

3

3 Answers

11
votes

Does that mean, that the content drawn in a view in its drawRect method call, is captured in a snapshot in saved in its backing core animation layer?

Yes. Everything uses layers under the hood. UIView's -drawRect will capture what you draw and (as far as I know) set the content on a sublayer of the view. It might even do this on the main layer object. That's where the 'snapshot' is saved.

If not, does that mean that CALayer is used to render "static" content, content that doesn't change very often, and drawRect is used to render content that changes often, for example in a game app?

How often the content changes doesn't really affect the choice. There is not much difference in using drawRect vs. manually creating CALayers. It depends on how you want to organize the sub-elements in your views, or if you want to create low level reusable layer objects without the details of UIView (e.g. CATextLayer). If you have various different sub-elements to draw then you may split them into different layers with their own custom drawing code. If you just have one simple piece of content to draw, you can do that all in a single drawRect implementation.

Having said this, you do need to be aware that each layer will end up being a separate GPU "element", so there can be performance benefits to reducing the number of layers you have, or using the shouldRasterize+rasterizationScale properties of a parent layer. This will take a snapshot of an entire layer hierarchy and create a single rasterized image to be rendered instead of n separate ones.

1
votes

Does that mean, that the content drawn in a view in its drawRect method call, is captured in a snapshot in saved in its backing core animation layer?

Two words: "implementation details"

If not, does that mean that CALayer is used to render "static" content, content that doesn't change very often, and drawRect is used to render content that changes often, for example in a game app?

Not exactly. Layers are very good at animating content (as hinted by the framework name Core Animation). drawRect is good for advanced drawing but can be to slow to redraw every frame (obviously depending on what your are drawing).

I didn't see any mention of the Core Animation Programming Guide in your question. It is a good place to learn more about the layer part of views.

0
votes

Every UIView has an underlying CALayer (which is what actually gets rendered on the screen).

A CALayer is just a bitmap (holds pixels). When you call setNeedsDisplay to your view the CALayer gets marked for redrawing. At the end of the run loop, after events are processed, a CGContextRef gets created and the drawRect delegate gets called. You then draw things to the created context which then gets copied into the bitmap and ultimately composited with other layers to be displayed on the screen.

So yes, the "snapshot" is stored in the CALayer. This is just an optimization so that the layers don't have to redraw themselves unless they're flagged to be redrawn (with setNeedsDisplay).