Graphics Reference
In-Depth Information
Core Graphics Drawing
After you have eliminated views or layers that are not contributing to the display onscreen,
there might still be ways that you can reduce the layer count further. For example, if you
are using multiple
UILabel
or
UIImageView
instances to display static content, you can
potentially replace it all with a single view that uses
-drawRect:
to replicate the
appearance of a complex view hierarchy.
It might seem counterintuitive to do this because we know that software drawing is slower
than GPU compositing and requires additional memory, but in a situation where the
performance is limited by the number of layers, software drawing may actually
improve
the
performance by avoiding excessive layer allocation and manipulation.
Doing the drawing yourself in this case involves a similar performance tradeoff to
rasterizing, but means that you can remove sublayers from the layer tree altogether (as
opposed to just obscuring them, as you do when using
shouldRasterize
).
The
-renderInContext:
Method
Using Core Graphics to draw a static layout may sometimes be faster than using a hierarchy
of
UIView
instances, but using
UIView
instances is both more concise and more flexible
than writing the equivalent drawing code by hand, especially if you use Interface Builder to
do the layout. It would be a shame to have to sacrifice those benefits for the sake of
performance tuning.
Fortunately, you don't have to. Having a large number of views or layers is only a problem
if the layers are
actually attached to the screen
. Layers that are not connected to the layer
tree don't get sent to the render server and won't impact performance (after they've been
initially created and configured).
By using the
CALayer
-renderInContext:
method, you can draw a snapshot of a layer and
its sublayers into a Core Graphics context and capture the result as an image, which can
then be displayed directly inside a
UIImageView
, or as the
contents
of another
CALayer
.
Unlike using
shouldRasterize
—which still requires that the layers be attached to the layer
tree—with this approach there is no ongoing performance cost.
Responsibility for refreshing this image when the layer content changes would be up to you
(unlike using
shouldRasterize
, which handles caching and cache invalidation
automatically), but once the image has initially been generated, you save significant per-
frame performance overhead with this approach versus asking Core Animation to maintain
a complex layer tree.
This chapter examined the common performance bottlenecks when using Core Animation
layers and discussed how to avoid or mitigate them. You learned how to manage scenes
containing thousands of virtual layers by only creating a few hundred real ones. You also