CoreAnimation Guide
CoreAnimation Guide
Programming Guide
Contents
2
Contents
3
Contents
Animatable Properties 86
CALayer Animatable Properties 86
CIFilter Animatable Properties 89
4
Contents
Objective-C 9
5
Figures, Tables, and Listings
6
Figures, Tables, and Listings
Animatable Properties 86
Table B-1 Layer properties and their default animations 86
Table B-2 Default Implied Basic Animation 88
Table B-3 Default Implied Transition 88
7
Figures, Tables, and Listings
8
Objective-CSwift
9
About Core Animation
Core Animation is a graphics rendering and animation infrastructure available on both iOS and OS X that you
use to animate the views and other visual elements of your app. With Core Animation, most of the work required
to draw each frame of an animation is done for you. All you have to do is configure a few animation parameters
(such as the start and end points) and tell Core Animation to start. Core Animation does the rest, handing most
of the actual drawing work off to the onboard graphics hardware to accelerate the rendering. This automatic
graphics acceleration results in high frame rates and smooth animations without burdening the CPU and
slowing down your app.
If you are writing iOS apps, you are using Core Animation whether you know it or not. And if you are writing
OS X apps, you can take advantage of Core Animation with extremely little effort. Core Animation sits beneath
AppKit and UIKit and is integrated tightly into the view workflows of Cocoa and Cocoa Touch. Of course, Core
Animation also has interfaces that extend the capabilities exposed by your app’s views and give you more
fine-grained control over your app’s animations.
At a Glance
You may never need to use Core Animation directly, but when you do you should understand the role that
Core Animation plays as part of your app’s infrastructure.
10
About Core Animation
At a Glance
Relevant Chapter: Core Animation Basics (page 13), Setting Up Layer Objects (page 26),
Relevant Chapters: , Animating Layer Content (page 43), Advanced Animation Tricks (page 63),
Layer Style Property Animations (page 77), Animatable Properties (page 86)
11
About Core Animation
How to Use This Document
Prerequisites
You should already understand the view architecture of your target platform and be familiar with how to create
view-based animations. If not, you should read one of the following documents:
● For iOS apps, you should understand the view architecture described in View Programming Guide for iOS .
● For OS X apps, you should understand the view architecture described in View Programming Guide .
See Also
For examples of how to implement specific types of animations using Core Animation, see Core Animation
Cookbook .
12
Core Animation Basics
SwiftObjective-C
Core Animation provides a general purpose system for animating views and other visual elements of your app.
Core Animation is not a replacement for your app’s views. Instead, it is a technology that integrates with views
to provide better performance and support for animating their content. It achieves this behavior by caching
the contents of views into bitmaps that can be manipulated directly by the graphics hardware. In some cases,
this caching behavior might require you to rethink how you present and manage your app’s content, but most
of the time you use Core Animation without ever knowing it is there. In addition to caching view content, Core
Animation also defines a way to specify arbitrary visual content, integrate that content with your views, and
animate it along with everything else.
You use Core Animation to animate changes to your app’s views and visual objects. Most changes relate to
modifying the properties of your visual objects. For example, you might use Core Animation to animate changes
to a view’s position, size, or opacity. When you make such a change, Core Animation animates between the
current value of the property and the new value you specify. You would typically not use Core Animation to
replace the content of a view 60 times a second, such as in a cartoon. Instead, you use Core Animation to move
a view’s content around the screen, fade that content in or out, apply arbitrary graphics transformations to
the view, or change the view’s other visual attributes.
13
Core Animation Basics
Layers Provide the Basis for Drawing and Animations
When a change triggers an animation, Core Animation passes the layer’s bitmap and state information to the
graphics hardware, which does the work of rendering the bitmap using the new information, as shown in
Figure 1-1. Manipulating the bitmap in hardware yields much faster animations than could be done in software.
Core Animation
Layer Object
Because it manipulates a static bitmap, layer-based drawing differs significantly from more traditional view-based
drawing techniques. With view-based drawing, changes to the view itself often result in a call to the view’s
drawRect: method to redraw content using the new parameters. But drawing in this way is expensive because
it is done using the CPU on the main thread. Core Animation avoids this expense by whenever possible by
manipulating the cached bitmap in hardware to achieve the same or similar effects.
Although Core Animation uses cached content as much as possible, your app must still provide the initial
content and update it from time to time. There are several ways for your app to provide a layer object with
content, which are described in detail in Providing a Layer’s Contents (page 30).
Layer-Based Animations
The data and state information of a layer object is decoupled from the visual presentation of that layer’s content
onscreen. This decoupling gives Core Animation a way to interpose itself and animate the change from the
old state values to new state values. For example, changing a layer’s position property causes Core Animation
14
Core Animation Basics
Layer Objects Define Their Own Geometry
to move the layer from its current position to the newly specified position. Similar changes to other properties
cause appropriate animations. Figure 1-2 illustrates a few of the types of animations you can perform on layers.
For a list of layer properties that trigger animations, see Animatable Properties (page 86).
During the course of an animation, Core Animation does all of the frame-by-frame drawing for you in hardware.
All you have to do is specify the start and end points of the animation and let Core Animation do the rest. You
can also specify custom timing information and animation parameters as needed; however, Core Animation
provides suitable default values if you do not.
For more information about how to initiate animations and configure animation parameters, see Animating
Layer Content (page 43).
15
Core Animation Basics
Layer Objects Define Their Own Geometry
Among the most common uses for point-based coordinates is to specify the size and position of the layer,
which you do using the layer’s bounds and position properties. The bounds defines the coordinate system
of the layer itself and encompasses the layer’s size on the screen. The position property defines the location
of the layer relative to its parent’s coordinate system. Although layers have a frame property, that property is
actually derived from the values in the bounds and position properties and is used less frequently.
The orientation of a layer’s bounds and frame rectangles always matches the default orientation of the
underlying platform. Figure 1-3 shows the default orientations of the bounds rectangle on both iOS and OS X.
In iOS, the origin of the bounds rectangle is in the top-left corner of the layer by default, and in OS X it is in
the bottom-left corner. If you share Core Animation code between iOS and OS X versions of your app, you
must take such differences into consideration.
One thing to note in Figure 1-3 (page 16) is that the position property is located in the middle of the layer.
That property is one of several whose definition changes based on the value in the layer’s anchorPoint
property. The anchor point represents the point from which certain coordinates originate and is described in
more detail in Anchor Points Affect Geometric Manipulations (page 17).
The anchor point is one of several properties that you specify using the unit coordinate system. Core Animation
uses unit coordinates to represent properties whose values might change when the layer’s size changes. You
can think of the unit coordinates as specifying a percentage of the total possible value. Every coordinate in
16
Core Animation Basics
Layer Objects Define Their Own Geometry
the unit coordinate space has a range of 0.0 to 1.0. For example, along the x-axis, the left edge is at the
coordinate 0.0 and the right edge is at the coordinate 1.0. Along the y-axis, the orientation of unit coordinate
values changes depending on the platform, as shown in Figure 1-4.
Figure 1-4 The default unit coordinate systems for iOS and OS X
iOS OS X
Note: Until OS X 10.8, the geometryFlipped property was a way to change the default orientation
of a layer’s y-axis when needed. Use of this property was sometimes necessary to correct the
orientation of a layer when flip transforms were in involved. For example, if a parent view used a flip
transform, the contents of its child views (and their corresponding layers) would often be inverted.
In such cases, setting the geometryFlipped property of the child layers to YES was an easy way
to correct the problem. In OS X 10.8 and later, AppKit manages this property for you and you should
not modify it. For iOS apps, it is recommended that you do not use the geometryFlipped property
at all.
All coordinate values, whether they are points or unit coordinates are specified as floating-point numbers. The
use of floating-point numbers allows you to specify precise locations that might fall between normal coordinate
values. The use of floating-point values is convenient, especially during printing or when drawing to a Retina
display where one point might be represented by multiple pixels. Floating-point values allow you to ignore
the underlying device resolution and just specify values at the precision you need.
17
Core Animation Basics
Layer Objects Define Their Own Geometry
Figure 1-5 demonstrates how changing the anchor point from its default value to a different value affects the
position property of a layer. Even though the layer has not moved within its parents’ bounds, moving the
anchor point from the center of the layer to the layer’s bounds origin changes the value in the position
property.
Figure 1-5 How the anchor point affects the layer’s position property
iOS OS X
18
Core Animation Basics
Layer Objects Define Their Own Geometry
Figure 1-6 shows how changing the anchor point affects transforms applied to the layer. When you apply a
rotation transform to the layer, the rotations occur around the anchor point. Because the anchor point is set
to the middle of the layer by default, this normally creates the kind of rotation behavior that you would expect.
However, if you change the anchor point, the results of the rotation are different.
19
Core Animation Basics
Layer Objects Define Their Own Geometry
use that property to scale or rotate the layer or change its position temporarily. The sublayerTransform
property defines additional transformations that apply only to the sublayers and is used most commonly to
add a perspective visual effect to the contents of a scene.
Transforms work by multiplying coordinate values through a matrix of numbers to get new coordinates that
represent the transformed versions of the original points. Because Core Animation values can be specified in
three dimensions, each coordinate point has four values that must be multiplied through a four-by-four matrix,
as shown in Figure 1-7. In Core Animation, the transform in the figure is represented by the CATransform3D
type. Fortunately, you do not have to modify the fields of this structure directly to perform standard
transformations. Core Animation provides a comprehensive set of functions for creating scale, translation, and
rotation matrices and for doing matrix comparisons. In addition to manipulating transforms using functions,
Core Animation extends key-value coding support to allow you to modify a transform using key paths. For a
list of key paths you can modify, see CATransform3D Key Paths (page 92).
Figure 1-8 shows the matrix configurations for some of the more common transformations you can make.
Multiplying any coordinate by the identity transform returns the exact same coordinate. For other
transformations, how the coordinate is modified depends entirely on which matrix components you change.
20
Core Animation Basics
Layer Trees Reflect Different Aspects of the Animation State
For example, to translate along the x-axis only, you would supply a nonzero value for the tx component of
the translation matrix and leave the ty and tz values to 0. For rotations, you would provide the appropriate
sine and cosine values of the target rotation angle.
For information about the functions you use to create and manipulate transforms, see Core Animation Function
Reference .
21
Core Animation Basics
Layer Trees Reflect Different Aspects of the Animation State
Each set of layer objects is organized into a hierarchical structure like the views in your app. In fact, for an app
that enables layers for all of its views, the initial structure of each tree matches the structure of the view hierarchy
exactly. However, an app can add additional layer objects—that is, layers not associated with a view—into the
layer hierarchy as needed. You might do this in situations to optimize your app’s performance for content that
does not require all the overhead of a view. Figure 1-9 shows the breakdown of layers found in a simple iOS
app. The window in the example contains a content view, which itself contains a button view and two standalone
layer objects. Each view has a corresponding layer object that forms part of the layer hierarchy.
22
Core Animation Basics
Layer Trees Reflect Different Aspects of the Animation State
For every object in the layer tree, there is a matching object in the presentation and render trees, as shown in
Figure 1-10. As was previously mentioned, apps primarily work with objects in the layer tree but may at times
access objects in the presentation tree. Specifically, accessing the presentationLayer property of an object
in the layer tree returns the corresponding object in the presentation tree. You might want to access that
object to read the current value of a property that is in the middle of an animation.
Framework
Render Tree
23
Core Animation Basics
The Relationship Between Layers and Views
Important: You should access objects in the presentation tree only while an animation is in flight. While
an animation is in progress, the presentation tree contains the layer values as they appear onscreen at that
instant. This behavior differs from the layer tree, which always reflects the last value set by your code and
is equivalent to the final state of the animation.
In iOS, every view is backed by a corresponding layer object but in OS X you must decide which views should
have layers. In OS X v10.8 and later, it probably makes sense to add layers to all of your views. However, you
are not required to do so and can still disable layers in cases where the overhead is unwarranted and unneeded.
Layers do increase your app’s memory overhead somewhat but their benefits often outweigh the disadvantage,
so it is always best to test the performance of your app before disabling layer support.
When you enable layer support for a view, you create what is referred to as a layer-backed view. In a layer-backed
view, the system is responsible for creating the underlying layer object and for keeping that layer in sync with
the view. All iOS views are layer-backed and most views in OS X are as well. However, in OS X, you can also
create a layer-hosting view, which is a view where you supply the layer object yourself. For a layer-hosting view,
AppKit takes a hands off approach with managing the layer and does not modify it in response to view changes.
Note: For layer-backed views, it is recommended that you manipulate the view, rather than its layer,
whenever possible. In iOS, views are just a thin wrapper around layer objects, so any manipulations
you make to the layer usually work just fine. But there are cases in both iOS and OS X where
manipulating the layer instead of the view might not yield the desired results. Wherever possible,
this document points out those pitfalls and tries to provide ways to help you work around them.
In addition to the layers associated with your views, you can also create layer objects that do not have a
corresponding view. You can embed these standalone layer objects inside of any other layer object in your
app, including those that are associated with a view. You typically use standalone layer objects as part of a
specific optimization path. For example, if you wanted to use the same image in multiple places, you could
24
Core Animation Basics
The Relationship Between Layers and Views
load the image once and associate it with multiple standalone layer objects and add those objects to the layer
tree. Each layer then refers to the source image rather than trying to create its own copy of that image in
memory.
For information about how to enable layer support for your app’s views, see Enabling Core Animation Support
in Your App (page 26). For information on how to create a layer object hierarchy, and for tips on when you
might do so, see Building a Layer Hierarchy (page 53).
25
Setting Up Layer Objects
Objective-CSwift
Layer objects are at the heart of everything you do with Core Animation. Layers manage your app’s visual
content and provide options for modifying the style and visual appearance of that content. Although iOS apps
have layer support enabled automatically, developers of OS X apps must enable it explicitly before they can
take advantage of the performance benefits. Once enabled, you need to understand how to configure and
manipulate your app’s layers to get the effects you want.
Enabling layer support in one of the preceding ways creates a layer-backed view. With a layer-backed view,
the system takes responsibility for creating the underlying layer object and for keeping that layer updated. In
OS X, it is also possible to create a layer-hosting view, whereby your app actually creates and manages the
underlying layer object. (You cannot create layer-hosting views in iOS.) For more information on how to create
a layer-hosting view, see Layer Hosting Lets You Change the Layer Object in OS X (page 28).
26
Setting Up Layer Objects
Changing the Layer Object Associated with a View
Changing the layer class of a view is very straightforward; an example is shown in Listing 2-1. All you have to
do is override the layerClass method and return the class object you want to use instead. Prior to display,
the view calls the layerClass method and uses the returned class to create a new layer object for itself. Once
created, a view’s layer object cannot be changed.
+ (Class) layerClass {
For a list of layer classes and how you use them, see Different Layer Classes Provide Specialized Behaviors (page
29).
27
Setting Up Layer Objects
Changing the Layer Object Associated with a View
For a list of layer classes and how you use them, see Different Layer Classes Provide Specialized Behaviors (page
29).
When you call the setLayer: method of your view and provide a layer object, AppKit takes a hands-off
approach to that layer. Normally, AppKit updates a view’s layer object but in the layer-hosting situation it does
not for most properties.
To create a layer-hosting view, create your layer object and associate it with the view before displaying the
view onscreen, as shown in Listing 2-2. In addition to setting the layer object, you must still call the
setWantsLayer: method to let the view know that it should use layers.
// Create myView...
[myView setWantsLayer:YES];
[myView setLayer:hostedLayer];
If you choose to host layers yourself, you must set the contentsScale property yourself and provide
high-resolution content at appropriate times. For more information about high-resolution content and scale
factors, see Working with High-Resolution Images (page 35).
28
Setting Up Layer Objects
Changing the Layer Object Associated with a View
Class Usage
CAGradientLayer Used to draw a color gradient that fills the shape of the layer
(within the bounds of any rounded corners).
CAMetalLayer Used to set up and vend drawable textures for rendering layer
content using Metal.
CAEAGLLayer/CAOpenGLLayer Used to set up the backing store and context for rendering layer
content using OpenGL ES (iOS) or OpenGL (OS X).
CAReplicatorLayer Used when you want to make copies of one or more sublayers
automatically. The replicator makes the copies for you and uses
the properties you specify to alter the appearance or attributes of
the copies.
CAShapeLayer Used to draw a cubic Bezier spline. Shape layers are advantageous
for drawing path-based shapes because they always result in a
crisp path, as opposed to a path you draw into a layer’s backing
store, which would not look as good when scaled. However, the
crisp results do involve rendering the shape on the main thread
and caching the results.
CATiledLayer Used to manage a large image that can be divided into smaller
tiles and rendered individually with support for zooming in and
out of the content.
CATransformLayer Used to render a true 3D layer hierarchy, rather than the flattened
layer hierarchy implemented by other layer classes.
29
Setting Up Layer Objects
Providing a Layer’s Contents
Class Usage
The only time you need to worry about providing content for a layer is when you create the layer object
yourself. If your app contains nothing but layer-backed views, you do not have to worry about using any of
the preceding techniques to provide layer content. Layer-backed views automatically provide the contents for
their associated layers in the most efficient way possible.
The image you assign to a layer must be a CGImageRef type. (In OS X v10.6 and later, you can also assign an
NSImage object.) When assigning images, remember to provide an image whose resolution matches the
resolution of the native device. For devices with Retina displays, this might also require you to adjust the
contentsScale property of the image. For information on using high-resolution content with your layers,
see Working with High-Resolution Images (page 35).
30
Setting Up Layer Objects
Providing a Layer’s Contents
The delegate object must implement either the displayLayer: or drawLayer:inContext: method. If the
delegate implements both the displayLayer: and drawLayer:inContext: method, the layer calls only
the displayLayer: method.
Overriding the displayLayer: method is most appropriate for situations when your app prefers to load or
create the bitmaps it wants to display. Listing 2-3 shows a sample implementation of the displayLayer:
delegate method. In this example, the delegate uses a helper object to load and display the image it needs.
The delegate method selects which image to display based on its own internal state, which in the example is
a custom property called displayYesImage.
- (void)displayLayer:(CALayer *)theLayer {
if (self.displayYesImage) {
else {
If you do not have prerendered images or a helper object to create bitmaps for you, your delegate can draw
the content dynamically using the drawLayer:inContext: method. Listing 2-4 shows a sample
implementation of the drawLayer:inContext: method. In this example, the delegate draws a simple curved
path using a fixed width and the current rendering color.
31
Setting Up Layer Objects
Providing a Layer’s Contents
CGPathMoveToPoint(thePath,NULL,15.0f,15.f);
CGPathAddCurveToPoint(thePath,
NULL,
15.f,250.0f,
295.0f,250.0f,
295.0f,15.0f);
CGContextBeginPath(theContext);
CGContextAddPath(theContext, thePath);
CGContextSetLineWidth(theContext, 5);
CGContextStrokePath(theContext);
CFRelease(thePath);
For layer-backed views with custom content, you should continue to override the view’s methods to do your
drawing. A layer-backed view automatically makes itself the delegate of its layer and implements the needed
delegate methods, and you should not change that configuration. Instead, you should implement your view’s
drawRect: method to draw your content.
In OS X v10.8 and later, an alternative to drawing is to provide a bitmap by overriding the wantsUpdateLayer
and updateLayer methods of your view. Overriding wantsUpdateLayer and returning YES causes the
NSView class to follow an alternate rendering path. Instead of calling drawRect:, the view calls your
updateLayer method, the implementation of which must assign a bitmap directly to the layer’s contents
property. This is the one scenario where AppKit expects you to set the contents of a view’s layer object directly.
32
Setting Up Layer Objects
Providing a Layer’s Contents
When subclassing, you can use either of the following techniques to draw your layer’s content:
● Override the layer’s display method and use it to set the contents property of the layer directly.
● Override the layer’s drawInContext: method and use it to draw into the provided graphics context.
Which method you override depends on how much control you need over the drawing process. The display
method is the main entry point for updating the layer’s contents, so overriding that method puts you in
complete control of the process. Overriding the display method also means that you are responsible for
creating the CGImageRef to be assigned to the contents property. If you just want to draw content (or have
your layer manage the drawing operation), you can override the drawInContext: method instead and let
the layer create the backing store for you.
The values you can assign to the contentsGravity property are divided into two categories:
● The position-based gravity constants allow you to pin your image to a particular edge or corner of the
layer’s bounds rectangle without scaling the image.
● The scaling-based gravity constants allow you to stretch the image using one of several options, some of
which preserve the aspect ratio and some of which do not.
Figure 2-1 shows the how the position-based gravity settings affect your images. With the exception of the
kCAGravityCenter constant, each constant pins the image to a particular edge or corner of the layer’s
bounds rectangle. The kCAGravityCenter constant centers the image in the layer. None of these constants
33
Setting Up Layer Objects
Providing a Layer’s Contents
cause the image to be scaled in any way, so the image is always rendered at its original size. If the image is
bigger than the layer’s bounds, this may result in portions of the image being clipped, and if the image is
smaller, the portions of the layer that are not covered by the image reveal the layer’s background color, if set.
Figure 2-2 shows how the scaling-based gravity constants affect your images. All of these constants scale the
image if it does not fit exactly within the bounds rectangle of the layer. The difference between the modes is
how they deal with the image’s original aspect ratio. Some modes preserve it and others do not. By default, a
layer’s contentsGravity property is set to the kCAGravityResize constant, which is the only mode that
does not preserve the image aspect ratio.
34
Setting Up Layer Objects
Adjusting a Layer’s Visual Style and Appearance
Changing the value of the contentsScale property is only necessary if you are assigning a bitmap to your
layer directly. A layer-backed view in UIKit and AppKit automatically sets the scale factor of its layer to an
appropriate value based on the screen resolution and the content managed by the view. For example, if you
assign an NSImage object to the contents property of a layer in OS X, AppKit looks to see if there are both
standard- and high-resolution variants of the image. If there are, AppKit uses the correct variant for the current
resolution and sets the value of the contentsScale property to match.
In OS X, the position-based gravity constants affect the way image representations are chosen from an NSImage
object assigned to the layer. Because these constants do not cause the image to be scaled, Core Animation
relies on the contentsScale property to pick the image representation with the most appropriate pixel
density.
35
Setting Up Layer Objects
Adjusting a Layer’s Visual Style and Appearance
Listing 2-5 shows the code needed to set the background color and border for a layer. All of these properties
are animatable.
myLayer.borderWidth = 3.0;
36
Setting Up Layer Objects
Adjusting a Layer’s Visual Style and Appearance
Note: You can use any type of color for the background of a layer, including colors that have
transparency or use a pattern image. When using pattern images, though, be aware that Core
Graphics handles the rendering of the pattern image and does so using its standard coordinate
system, which is different than the default coordinate system in iOS. As such, images rendered on
iOS appear upside down by default unless you flip the coordinates.
If you set your layer’s background color to an opaque color, consider setting the layer’s opaque property to
YES. Doing so can improve performance when compositing the layer onscreen and eliminates the need for
the layer’s backing store to manage an alpha channel. You must not mark a layer as opaque if it also has a
nonzero corner radius, though.
To apply a corner radius to your layer, specify a value for the cornerRadius property of the layer. The radius
value you specify is measured in points and applied to all four corners of the layer prior to display.
37
Setting Up Layer Objects
Adjusting a Layer’s Visual Style and Appearance
The opacity value for layer shadows is set to 0 by default, which effectively hides the shadow. Changing the
opacity to a nonzero value causes Core Animation to draw the shadow. Because shadows are positioned directly
under the layer by default, you might also need to change the shadow’s offset before you can see it. It is
important to remember, though, that the offsets you specify for the shadow are applied using the layer’s native
coordinate system, which is different on iOS and OS X. Figure 2-5 shows a layer with a shadow that extends
down and to the right of the layer. In iOS, this requires specifying a positive value for the y axis but in OS X the
value needs to be negative.
When adding shadows to a layer, the shadow is part of the layer’s content but actually extends outside the
layer’s bounds rectangle. As a result, if you enable the masksToBounds property for the layer, the shadow
effect is clipped around the edges. If your layer contains any transparent content, this can cause an odd effect
where the portion of the shadow directly under your layer is still visible but the part extending beyond your
layer is not. If you want a shadow but also want to use bounds masking, you use two layers instead of one.
Apply the mask to the layer containing your content and then embed that layer inside a second layer of the
exact same size that has the shadow effect enabled.
For examples of how shadows are applied to layers, see Shadow Properties (page 82).
38
Setting Up Layer Objects
Adjusting a Layer’s Visual Style and Appearance
For a given layer, you can apply filters to both the foreground and background content of the layer. The
foreground content consists of everything that the layer itself contains, including the image in its contents
property, its background color, its border, and the content of its sublayers. The background content is the
content that is directly under the layer but not actually part of the layer itself. The background content of most
layers is the content of its immediate superlayer, which may be wholly or partially obscured by the layer. For
example, you might apply a blur filter to the background content when you want the user to focus on the
layer’s foreground content.
You specify filters by adding CIFilter objects to the following properties of your layer:
● The filters property contains an array of filters that affect the layer’s foreground content only.
● The backgroundFilters property contains an array of filters that affect the layer’s background content
only.
● The compositingFilter property defines how the layer’s foreground and background content are
composited together.
To add a filter to a layer, you must first locate and create the CIFilter object and then configure it before
adding it to your layer. The CIFilter class includes several class methods for locating the available Core
Image filters, such as the filterWithName: method. Creating the filter is only the first step, though. Many
filters have parameters that define how the filter modifies an image. For example, a box blur filter has an input
radius parameter that affects the amount of blur that is applied. You should always provide values for these
parameters as part of the filter configuration process. However, one common parameter that you do not need
to specify is the input image, which is provided by the layer itself.
When adding filters to layers, it is best to configure the filter parameters prior to adding the filter to the layer.
The main reason for doing so is that once added to the layer, you cannot modify the CIFilter object itself.
However, you can use the layer’s setValue:forKeyPath: method to change filter values after the fact.
39
Setting Up Layer Objects
The Layer Redraw Policy for OS X Views Affects Performance
Listing 2-6 shows how to create and apply a pinch distortion filter to a layer object. This filter pinches the
source pixels of the layer inward, distorting those pixels closest to the specified center point the most. Notice
in the example that you do not need to specify the input image for the filter because the layer’s image is used
automatically.
For information about the available Core Image filters, see Core Image Filter Reference .
Each view defines a layerContentsRedrawPolicy method that returns the redraw policy for the view’s
layer. You set the policy using the setLayerContentsRedrawPolicy: method. To preserve compatibility
with its traditional drawing model, AppKit sets the redraw policy to
NSViewLayerContentsRedrawDuringViewResize by default. However, you can change the policy to any
of the values in Table 2-2. Notice that the recommended redraw policy is not the default policy.
40
Setting Up Layer Objects
The Layer Redraw Policy for OS X Views Affects Performance
Policy Usage
NSViewLayerContents- This is the recommended policy. With this policy, view geometry changes
RedrawOnSetNeeds- do not automatically cause the view to update its layer’s contents. Instead,
Display the layer’s existing contents are stretched and manipulated to facilitate
the geometry changes. To force the view to redraw itself and update the
layer’s contents, you must explicitly call the view’s setNeedsDisplay:
method.
This policy most closely represents the standard behavior for Core
Animation layers. However, it is not the default policy and must be set
explicitly.
NSViewLayerContents- This is the default redraw policy. This policy maintains maximum
RedrawDuringView- compatibility with traditional AppKit drawing by recaching the layer’s
Resize contents whenever the view’s geometry changes. This behavior results
in the view’s drawRect: method being called multiple times on your
app’s main thread during the resize operation.
NSViewLayerContents- With this policy, AppKit draws the layer at its final size prior to any resize
RedrawBeforeView- operations and caches that bitmap. The resize operation uses the cached
Resize bitmap as the starting image, scaling it to fit the old bounds rectangle. It
then animates the bitmap to its final size. This behavior can cause the
view’s contents to appear stretched or distorted at the beginning of an
animation and is better in situations where the initial appearance is not
important or not noticeable.
NSViewLayerContents- With this policy, AppKit does not update the layer at all, even when you
RedrawNever call the setNeedsDisplay: method. This policy is most appropriate for
views whose contents never change and where the size of the view
changes infrequently if at all. For example, you might use this for views
that display fixed-size content or background elements.
View redraw policies alleviate the need to use standalone sublayers to improve drawing performance. Prior to
the introduction of view redraw policies, there were some layer-backed views that drew more frequently than
was needed and thereby caused performance issues. The solution to these performance issues was to use
sublayers to present those portions of the view’s content that did not require regular redrawing. With the
introduction of redraw policies in OS X v10.6, it is now recommended that you set a layer-backed view’s redraw
policy to an appropriate value, rather than creating explicit sublayer hierarchies.
41
Setting Up Layer Objects
Adding Custom Properties to a Layer
For information about how to set and get custom properties, see Key-Value Coding Compliant Container
Classes (page 90). For information about adding actions to your layer objects, see Changing a Layer’s Default
Behavior (page 70).
42
Animating Layer Content
SwiftObjective-C
The infrastructure provided by Core Animation makes it easy to create sophisticated animations of your app’s
layers, and by extension to any views that own those layers. Examples include changing the size of a layer’s
frame rectangle, changing its position onscreen, applying a rotation transform, or changing its opacity. With
Core Animation, initiating an animation is often as simple as just changing the property but you can also create
animations and set the animation parameters explicitly.
For information about creating more advanced animations, see Advanced Animation Tricks (page 63).
Simple animations involve changing the properties of a layer and letting Core Animation animate those changes
over time. Layers define many properties that affect the visible appearance of the layer. Changing one of these
properties is a way to animate the appearance change. For example, changing the opacity of the layer from
1.0 to 0.0 causes the layer to fade out and become transparent.
Important: Although you can sometimes animate layer-backed views directly using Core Animation
interfaces, doing so often requires extra steps. For more information about how how to use Core Animation
in conjunction with layer-backed views, see How to Animate Layer-Backed Views (page 50).
To trigger implicit animations, all you have to do is update the properties of your layer object. When modifying
layer objects in the layer tree, your changes are reflected immediately by those objects. However, the visual
appearance of the layer objects does not change immediately. What happens instead is that Core Animation
uses your changes as a trigger to create and schedule one or more implicit animations for execution. Thus,
making a change like the one in Listing 3-1 causes Core Animation to create an animation object for you and
schedule that animation to run starting in the next update cycle.
43
Animating Layer Content
Animating Simple Changes to a Layer’s Properties
theLayer.opacity = 0.0;
To make the same change explicitly using an animation object, create a CABasicAnimation object and use
that object to configure the animation parameters. You can set the start and end values for the animation,
change the duration, or change any other animation parameters before adding the animation to a layer. Listing
3-2 shows how to fade out a layer using an animation object. When creating the object, you specify the key
path for the property you want to animate and then set your animation parameters. To execute the animation,
you use the addAnimation:forKey: method to add it to the layers you want to animate.
fadeAnim.duration = 1.0;
// Change the actual data value in the layer to the final value.
theLayer.opacity = 0.0;
Tip: When creating an explicit animation, it is recommended that you always assign a value to the
fromValue property of the animation object. If you do not specify a value for this property, Core
animation uses the layer’s current value as the starting value. If you already updated the property
to its final value, that might not yield the results you want.
Unlike an implicit animation, which updates the layer object’s data value, an explicit animation does not modify
the data in the layer tree. Explicit animations only produce the animations. At the end of the animation, Core
Animation removes the animation object from the layer and redraws the layer using its current data values. If
you want the changes from an explicit animation to be permanent, you must also update the layer’s property
as shown in the preceding example.
Implicit and explicit animations normally begin executing after the current run loop cycle ends, and the current
thread must have a run loop in order for animations to be executed. If you change multiple properties, or if
you add multiple animation objects to a layer, all of those property changes are animated at the same time.
44
Animating Layer Content
Using a Keyframe Animation to Change Layer Properties
For example, you can fade a layer while moving it offscreen by configuring both animations at the same time.
However, you can also configure animation objects to start at a particular time. For more information about
modifying animation timing, see Customizing the Timing of an Animation (page 65).
Figure 3-1 shows a 5-second animation of a layer’s position property. The position is animated to follow a
path, which was specified using a CGPathRef data type. The code for this animation is shown in Listing
3-3 (page 45).
Listing 3-3 shows the code used to implement the animation in Figure 3-1. The path object in this example is
used to define the position of the layer for each frame of the animation.
CGPathMoveToPoint(thePath,NULL,74.0,74.0);
CGPathAddCurveToPoint(thePath,NULL,74.0,500.0,
320.0,500.0,
320.0,74.0);
CGPathAddCurveToPoint(thePath,NULL,320.0,500.0,
566.0,500.0,
45
Animating Layer Content
Using a Keyframe Animation to Change Layer Properties
566.0,74.0);
CAKeyframeAnimation * theAnimation;
// Create the animation object, specifying the position property as the key path.
theAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
theAnimation.path=thePath;
theAnimation.duration=5.0;
When specifying an array of values, what you put into the array depends on the data type required by the
property. You can add some objects to an array directly; however, some objects must be cast to id before
being added, and all scalar types or structs must be wrapped by an object. For example:
● For properties that take a CGRect (such as the bounds and frame properties), wrap each rectangle in an
NSValue object.
● For the layer’s transform property, wrap each CATransform3D matrix in an NSValue object. Animating
this property causes the keyframe animation to apply each transform matrix to the layer in turn.
● For the borderColor property, cast each CGColorRef data type to the type id before adding it to the
array.
● For properties that take a CGFloat value, wrap each value in an NSNumber object before adding it to the
array.
● When animating the layer’s contents property, specify an array of CGImageRef data types.
46
Animating Layer Content
Using a Keyframe Animation to Change Layer Properties
For properties that take a CGPoint data type, you can create an array of points (wrapped in NSValue objects)
or you can use a CGPathRef object to specify the path to follow. When you specify an array of points, the
keyframe animation object draws a straight line between each successive point and follows that path. When
you specify a CGPathRef object, the animation starts at the beginning point of the path and follows its outline,
including along any curved surfaces. You can use either an open or closed path.
If you want to handle the animation timing yourself, use the kCAAnimationLinear or kCAAnimationCubic
mode and the keyTimes and timingFunctions properties. The keyTimes defines the points in time at
which to apply each keyframe value. The timing for all intermediate values is controlled by the timing functions,
which allow you to apply ease-in or ease-out curves to each segment. If you do not specify any timing functions,
the timing is linear.
47
Animating Layer Content
Stopping an Explicit Animation While It Is Running
When you remove an animation from a layer, Core Animation responds by redrawing the layer using its current
values. Because the current values are usually the end values of the animation, this can cause the appearance
of the layer to jump suddenly. If you want the layer’s appearance to remain where it was on the last frame of
the animation, you can use the objects in the presentation tree to retrieve those final values and set them on
the objects in the layer tree.
For information about pausing an animation temporarily, see Listing 5-4 (page 66).
Listing 3-4 shows how you would use an animation group to perform two border-related animations at the
same time and with the same duration.
// Animation 1
48
Animating Layer Content
Detecting the End of an Animation
widthAnim.values = widthValues;
widthAnim.calculationMode = kCAAnimationPaced;
// Animation 2
colorAnim.values = colorValues;
colorAnim.calculationMode = kCAAnimationPaced;
// Animation group
group.duration = 5.0;
A more advanced way to group animations together is to use a transaction object. Transactions provide more
flexibility by allowing you to create nested sets of animations and assign different animation parameters for
each. For information about how to use transaction objects, see Explicit Transactions Let You Change Animation
Parameters (page 67).
There are two different ways to be notified about the state of an animation:
● Add a completion block to the current transaction using the setCompletionBlock: method. When all
of the animations in the transaction finish, the transaction executes your completion block.
● Assign a delegate to your CAAnimation object and implement the animationDidStart: and
animationDidStop:finished: delegate methods.
49
Animating Layer Content
How to Animate Layer-Backed Views
If you want to chain two animations together so that one starts when the other finishes, do not use animation
notifications. Instead, use the beginTime property of your animation objects to start each one at the desired
time. To chain two animations together, set the start time of the second animation to the end time of the first
animation. For more information about animation and timing values, see Customizing the Timing of an
Animation (page 65).
If you want to use Core Animation classes to initiate animations, you must issue all of your Core Animation
calls from inside a view-based animation block. The UIView class disables layer animations by default but
reenables them inside animation blocks. So any changes you make outside of an animation block are not
animated. Listing 3-5 shows an example of how to change a layer’s opacity implicitly and its position explicitly.
In this example, the myNewPosition variable is calculated beforehand and captured by the block. Both
animations start at the same time but the opacity animation runs with the default timing while the position
animation runs with the timing specified in its animation object.
myView.layer.opacity = 0.0;
theAnim.duration = 3.0;
50
Animating Layer Content
How to Animate Layer-Backed Views
}];
Important: The preceding restrictions do not apply to layer-hosting views. If you created the layer object
and associated it with a view manually, you are responsible for modifying the properties of that layer and
keeping the corresponding view object in sync.
AppKit disables implicit animations for its layer-backed views by default. The view’s animator proxy object
reenables implicit animations automatically for you. If you want to animate layer properties directly, you can
also programmatically reenable implicit animations by changing the allowsImplicitAnimation property
of the current NSAnimationContext object to YES. Again, you should do this only for animatable properties
that are not in the preceding list.
51
Animating Layer Content
How to Animate Layer-Backed Views
For more information on constraints and how you use them to manage the layout of your views, see Auto
Layout Guide .
52
Building a Layer Hierarchy
SwiftObjective-C
Most of the time, the best way to use layers in your app is to use them in conjunction with a view object.
However, there are times when you might need to enhance your view hierarchy by adding additional layer
objects to it. You might use use layers when doing so offers better performance or lets you implement a feature
that would be difficult to do with views alone. In those situations, you need to know how to manage the layer
hierarchies you create.
Important: In OS X v10.8 and later, it is recommended that you minimize your use of layer hierarchies and
just use layer-backed views. The layer redraw policies introduced in that version of OS X let you customize
the behavior of your layer-backed views and still get the kind of performance you might have gotten
previously using standalone layers.
Adding addSublayer: Adds a new sublayer object to the current layer. The
layers sublayer is added to the end of the layer’s list of
sublayers. This causes the sublayer to appear on top
of any siblings with the same value in their zPosition
property.
53
Building a Layer Hierarchy
Arranging Layers into a Layer Hierarchy
Inserting insertSublayer: Inserts the sublayer into the sublayer hierarchy at the
layers above: specified index or at a position relative to another
insertSublayer:
sublayer. When inserting above or below another
sublayer, you are only specifying the sublayer’s position
atIndex:
in the sublayers array. The actual visibility of the
insertSublayer: layers is determined primarily by the value in their
below: zPosition property and secondarily by their position
in the sublayers array.
You use the preceding methods when working with layer objects you created yourself. You would not use
these methods to arrange layers that belong to layer-backed views. However, a layer-backed view can act as
the parent for standalone layers you create yourself.
You set the size of a sublayer using the bounds property and set its position within its superlayer using the
position property. The origin of the bounds rectangle is almost always (0, 0) and the size is whatever size
you want for the layer specified in points. The value in the position property is interpreted relative to the
layer’s anchor point, which is located in the center of the layer by default. If you do not assign values to these
properties, Core Animation sets the initial width and height of the layer to 0 and sets the position to (0, 0).
54
Building a Layer Hierarchy
Adjusting the Layout of Your Layer Hierarchies
Important: Always use integral numbers for the width and height of your layer.
Most other layer changes affect any contained sublayers in predictable ways. For example, applying a rotation
transform to a layer rotates that layer and all of its sublayers. Similarly, changing a layer’s opacity changes the
opacity of its sublayers. Changes to the size of a layer follow the rules for layout that are described in Adjusting
the Layout of Your Layer Hierarchies (page 55).
Layer-level layout is only relevant if you are building layer hierarchies using standalone layer objects you
created. If your app’s layers are all associated with views, use the view-based layout support to update the size
and position of your views in response to changes.
Figure 4-1 shows the attributes that you can use to define a constraint and the aspect of the layer that they
impact. You can use constraints to change the position the layer based on the position of its edges of midpoints
relative to another layer. You can also use them to change the size of the layer. The changes you make can be
55
Building a Layer Hierarchy
Adjusting the Layout of Your Layer Hierarchies
proportional to the superlayer or relative to another layer. You can even add a scaling factor or constant to
the resulting change. This extra flexibility makes it possible to control a layer’s size and position very precisely
using a simple set of rules.
Each constraint object encapsulates one geometry relationship between two layers along the same axis. A
maximum of two constraint objects may be assigned to each axis and it is those two constraints that determine
which attribute is changeable. For example, if you specify constraints for the left and right edge of the layer,
the size of the layer changes. If you specify constraints for the left edge and width of the layer, the location of
the layer’s right edge changes. If you specify a single constraint for one of the layer’s edges, Core Animation
creates an implicit constraint that keeps the size of the layer fixed in the given dimension.
When creating constraints, you must always specify three pieces of information:
● The aspect of the layer that you want to constrain
● The layer to use as a reference
● The aspect of the reference layer to use in the comparison
Listing 4-1 shows a simple constraint that pins the vertical midpoint of a layer to the vertical midpoint of its
superlayer. When referring to the superlayer, use the string superlayer. This string is a special name reserved
for referring to the superlayer. Using it eliminates needing to have a pointer to the layer or know the layer’s
name. It also allows you to change the superlayer and have the constraint apply automatically to the new
parent. (When creating constraints relative to sibling layers, you must identify the sibling layer using its name
property.)
56
Building a Layer Hierarchy
Adjusting the Layout of Your Layer Hierarchies
relativeTo:@"superlayer"
attribute:kCAConstraintMidY]];
To apply constraints at runtime, you must attach the shared CAConstraintLayoutManager object to the
immediate superlayer. Each layer is responsible for managing the layout of its sublayers. Assigning the layout
manager to the parent tells Core Animation to apply the constraints defined by its children. The layout manager
object applies the constraints automatically. After assigning it to the parent layer, you do not have to tell it to
update the layout.
To see how constraints work in a more specific scenario, consider Figure 4-2. In this example, the design requires
that the width and height of layerA remain unchanged and that layerA remain centered inside its superlayer.
In addition, the width of layerB must match that of layerA, the top edge of layerB must remain 10 points
below the bottom edge of layerA, and the bottom edge of layerB must remain 10 points above the bottom
edge of the superlayer. Listing 4-2 (page 57) shows the code that you would use to create the sublayers and
constraints for this example.
// Create and set a constraint layout manager for the parent layer.
theLayer.layoutManager=[CAConstraintLayoutManager layoutManager];
57
Building a Layer Hierarchy
Adjusting the Layout of Your Layer Hierarchies
layerA.name = @"layerA";
layerA.bounds = CGRectMake(0.0,0.0,100.0,25.0);
layerA.borderWidth = 2.0;
relativeTo:@"superlayer"
attribute:kCAConstraintMidY]];
[layerA addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidX
relativeTo:@"superlayer"
attribute:kCAConstraintMidX]];
[theLayer addSublayer:layerA];
layerB.name = @"layerB";
layerB.borderWidth = 2.0;
relativeTo:@"layerA"
attribute:kCAConstraintWidth]];
relativeTo:@"layerA"
attribute:kCAConstraintMidX]];
// Position the top edge of layerB 10 points from the bottom edge of layerA.
relativeTo:@"layerA"
attribute:kCAConstraintMinY
58
Building a Layer Hierarchy
Adjusting the Layout of Your Layer Hierarchies
offset:-10.0]];
relativeTo:@"superlayer"
attribute:kCAConstraintMinY
offset:+10.0]];
[theLayer addSublayer:layerB];
One interesting thing to note about Listing 4-2 (page 57) is that the code never sets the size of layerB
explicitly. Because of the defined constraints, the width and height of layerB are set automatically every time
the layout is updated. Therefore, setting the size using the bounds rectangle is unnecessary.
Warning: When creating constraints, do not create circular references among your constraints. Circular
constraints make it impossible to calculate the needed layout information. When such circular references
are encountered, the layout behavior is undefined.
To set up the autosizing rules for a layer, you must assign the appropriate constants to the autoresizingMask
property of the layer. By default, layers are configured to have a fixed width and height. During layout, the
precise size and position of the layer is computed for you automatically by Core Animation and involve a
complex set of calculations based on many factors. Core Animation applies the autoresizing behaviors before
it asks your delegate to do any manual layout updates, so you can use the delegate to tweak the results of the
autoresizing layout as needed.
59
Building a Layer Hierarchy
Sublayers and Clipping
If you are implementing a custom layer subclass, your subclass can override the layoutSublayers method
and use that method (instead of a delegate) to handle any layout tasks. You should only override this method
in cases where you need complete control over the positioning of sublayers inside your custom layer class.
Replacing the default implementation prevents Core Animation from applying constraints or autoresizing rules
on OS X.
60
Building a Layer Hierarchy
Converting Coordinate Values Between Layers
The shape of a layer’s clipping mask includes the layer’s corner radius, if one is specified. Figure 4-3 shows a
layer that demonstrates how the masksToBounds property affects a layer with rounded corners. When the
property is set to NO, sublayers are displayed in their entirety, even if they extend beyond the bounds of their
parent layer. Changing the property to YES causes their content to be clipped.
In addition to converting point and rectangle values, you can also convert time values between layers using
the convertTime:fromLayer: and convertTime:toLayer: methods. Each layer defines its own local
time space and uses that time space to synchronize the beginning and ending of animations with the rest of
61
Building a Layer Hierarchy
Converting Coordinate Values Between Layers
the system. These time spaces are synchronized by default; however, if you change the animation speed for
one set of layers, the time space for those layers changes accordingly. You can use the time conversion methods
to to account for any such factors and ensure that the timing of both layers is synchronized.
62
Advanced Animation Tricks
There are many ways to configure your property-based or keyframe animations to do more for you. Apps that
need to perform multiple animations together or sequentially can use more advanced behaviors to synchronize
the timing of those animations or chain them together. You can also use other types of animation objects to
create visual transitions and other interesting animated effects.
To perform a transition animation, you create a CATransition object and add it to the layers involved in the
transition. You use the transition object to specify the type of transition to perform and the start and end points
of the transition animation. You do not need to use the entire transition animation either. The transition object
lets you specify the start and end progress values to use when animating. These values let you do things like
start or end an animation at its midpoint.
Listing 5-1 shows the code used to create an animated push transition between two views. In the example,
both myView1 and myView2 are located at the same position in the same parent view but only myView1 is
currently visible. The push transition causes myView1 to slide out to the left and fade until it is hidden while
myView2 slides in from the right and becomes visible. Updating the hidden property of both views ensures
that the visibility of both views is correct at the end of the animation.
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = kCATransitionPush;
63
Advanced Animation Tricks
Transition Animations Support Changes to Layer Visibility
transition.subtype = kCATransitionFromRight;
transition.duration = 1.0;
myView1.hidden = YES;
myView2.hidden = NO;
When two layers are involved in the same transition, you can use the same transition object for both. Using
the same transition object also simplifies the code you have to write. However, you can use different transition
objects and would definitely need to do so if the transition parameters for each layer are different.
Listing 5-2 shows how to use a Core Image filter to implement a transition effect on OS X. After configuring
the filter with the parameters you want, assign it to the filter property of the transition object. After that,
the process for applying the animation is the same as for other types of animation objects.
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.filter = aFilter;
transition.duration = 1.0;
[self.imageView2 setHidden:NO];
64
Advanced Animation Tricks
Customizing the Timing of an Animation
[self.imageView setHidden:YES];
Note: When using Core Image filters in an animation, the trickiest part is configuring the filter. For
example, with the bar swipe transition, specifying an input angle that is too high or too low might
make it seem as if no transition is happening. If you are not seeing the animation you expected, try
adjusting your filter parameters to different values to see if that changes the results.
When thinking about timing and animations, it is important to understand how layer objects work with time.
Each layer has its own local time that it uses to manage animation timing. Normally, the local time of two
different layers is close enough that you could specify the same time values for each and the user might not
notice anything. However, the local time of a layer can be modified by its parent layers or by its own timing
parameters. For example, changing the layer’s speed property causes the duration of animations on that layer
(and its sublayers) to change proportionally.
To assist you in making sure time values are appropriate for a given layer, the CALayer class defines the
convertTime:fromLayer: and convertTime:toLayer: methods. You can use these methods to convert
a fixed time value to the local time of a layer or to convert time values from one layer to another. The methods
take into account the media timing properties that might affect the local time of the layer and return a value
that you can use with the other layer. Listing 5-3 shows an example that you should use regularly to get the
current local time for a layer. The CACurrentMediaTime function is a convenience function that returns the
computer’s current clock time, which the method takes and converts to the layer’s local time.
65
Advanced Animation Tricks
Pausing and Resuming Animations
Once you have a time value in the layer’s local time, you can use that value to update the timing-related
properties of an animation object or layer. With these timing properties, you can achieve some interesting
animation behaviors, including:
● Use the beginTime property to set the start time of an animation. Normally, animations begin during the
next update cycle. You can use the beginTime parameter to delay the animation start time by several
seconds. The way to chain two animations together is to set the begin time of one animation to match
the end time of the other animation.
If you delay the start of an animation, you might also want to set the fillMode property to
kCAFillModeBackwards. This fill mode causes the layer to display the animation’s start value, even if
the layer object in the layer tree contains a different value. Without this fill mode, you would see a jump
to the final value before the animation starts executing. Other fill modes are available too.
● The autoreverses property causes an animation to execute for the specified duration and then return
to the starting value of the animation. You can combine this property with the repeatCount property
to animate back and forth between the start and end values. Setting the repeat count to a whole number
(such as 1.0) for an autoreversing animation causes the animation to stop on its starting value. Adding an
extra half step (such as a repeat count of 1.5) causes the animation to stop on its end value.
● Use the timeOffset property with group animations to start some animations at a later time than others.
-(void)pauseLayer:(CALayer*)layer {
layer.speed = 0.0;
layer.timeOffset = pausedTime;
-(void)resumeLayer:(CALayer*)layer {
66
Advanced Animation Tricks
Explicit Transactions Let You Change Animation Parameters
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
layer.beginTime = timeSincePause;
You create and manage transactions using the methods of the CATransaction class. To start (and implicitly
create) a new transaction call the begin class method; to end that transaction, call the commit class method.
In between those calls are the changes that you want to be part of the transaction. For example, to change
two properties of a layer, you could use the code in Listing 5-5.
[CATransaction begin];
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
[CATransaction commit];
One of the main reasons to use transactions is that within the confines of an explicit transaction, you can
change the duration, timing function, and other parameters. You can also assign a completion block to the
entire transaction so that your app can be notified when the group of animations finishes. Changing animation
parameters requires modifying the appropriate key in the transaction dictionary using the setValue:forKey:
method. For example, to change the default duration to 10 seconds, you would change the
kCATransactionAnimationDuration key, as shown in Listing 5-6.
[CATransaction begin];
67
Advanced Animation Tricks
Explicit Transactions Let You Change Animation Parameters
forKey:kCATransactionAnimationDuration];
[CATransaction commit];
You can nest transactions in situations where you want to provide different default values for different sets of
animations. To nest one transaction inside of another, just call the begin class method again. Each begin call
must be matched by a corresponding call to the commit method. Only after you commit the changes for the
outermost transaction does Core Animation begin the associated animations.
Listing 5-7 shows an example of one transaction nested inside another. In this example, the inner transaction
changes the same animation parameter as the outer transaction but uses a different value.
forKey:kCATransactionAnimationDuration];
theLayer.position = CGPointMake(0.0,0.0);
forKey:kCATransactionAnimationDuration];
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
68
Advanced Animation Tricks
Adding Perspective to Your Animations
When modifying the perspective of a scene, you need to modify the sublayerTransform matrix of the
superlayer that contains the layers being viewed. Modifying the superlayer simplifies the code you have to
write by applying the same perspective information to all of the child layers. It also ensures that the perspective
is applied correctly to sibling sublayers that overlap each other in different planes.
Listing 5-8 shows the way to create a simple perspective transform for a parent layer. In this case the custom
eyePosition variable specifies the relative distance along the z axis from which to view the layers. Usually
you specify a positive value for eyePosition to keep the layers oriented in the expected way. Larger values
result in a flatter scene while smaller values cause more dramatic visual differences between the layers.
perspective.m34 = -1.0/eyePosition;
myParentLayer.sublayerTransform = perspective;
With the parent layer configured, you can change the zPosition property of any child layers and observe
how their size changes based on their relative distance from the eye position.
69
Changing a Layer’s Default Behavior
Core Animation implements its implicit animation behaviors for layers using action objects. An action object
is an object that conforms to the CAAction protocol and defines some relevant behavior to perform on a
layer. All CAAnimation objects implement the protocol, and it is these objects that are usually assigned to be
executed whenever a layer property changes.
Animating properties is one type of action but you can define actions with almost any behavior you want. To
do that, though, you have to define your action objects and associate them with your app’s layer objects.
When you define an action object, you must decide how you want that action to be triggered. The trigger for
an action defines the key you use to register that action later. Action objects can be triggered by any of the
following situations:
● The value of one of the layer’s properties changed. This can be any of the layer’s properties and not just
the animatable ones. (You can also associate actions with custom properties you add to your layers.) The
key that identifies this action is the name of the property.
● The layer became visible or was added to a layer hierarchy. The key that identifies this action is
kCAOnOrderIn.
● The layer was removed from a layer hierarchy. The key that identifies this action is kCAOnOrderOut.
● The layer is about to be involved in a transition animation. The key that identifies this action is
kCATransition.
70
Changing a Layer’s Default Behavior
Action Objects Must Be Installed On a Layer to Have an Effect
If you provide an action object at any of the appropriate search points, the layer stops its search and executes
the returned action object. When it finds an action object, the layer calls that object’s
runActionForKey:object:arguments: method to perform the action. If the action you define for a given
key is already an instance of the CAAnimation class, you can use the default implementation of that method
to perform the animation. If you are defining your own custom object that conforms to the CAAction protocol,
you must use your object’s implementation of that method to take whatever actions are appropriate.
Where you install your action objects depends on how you intend to modify the layer.
● For actions that you might apply only in specific circumstances, or for layers that already use a delegate
object, provide a delegate and implement its actionForLayer:forKey: method.
● For layer objects that do not normally use a delegate, add the action to the layer’s actions dictionary.
● For actions related to custom properties that you define on the layer object, include the action in the
layer’s style dictionary.
● For actions that are fundamental to the behavior of the layer, subclass the layer and override the
defaultActionForKey: method.
71
Changing a Layer’s Default Behavior
Disable Actions Temporarily Using the CATransaction Class
Listing 6-1 shows an implementation of the delegate method used to provide action objects. In this case, the
delegate looks for changes to the layer’s contents property and swaps the new contents into place using a
transition animation.
- (id<CAAction>)actionForLayer:(CALayer *)theLayer
forKey:(NSString *)theKey {
CATransition *theAnimation=nil;
if ([theKey isEqualToString:@"contents"]) {
theAnimation.duration = 1.0;
theAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseIn];
theAnimation.type = kCATransitionPush;
theAnimation.subtype = kCATransitionFromRight;
return theAnimation;
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
[aLayer removeFromSuperlayer];
72
Changing a Layer’s Default Behavior
Disable Actions Temporarily Using the CATransaction Class
[CATransaction commit];
For more information about using transaction objects to manage animation behavior, see Explicit Transactions
Let You Change Animation Parameters (page 67).
73
Improving Animation Performance
SwiftObjective-C
Core Animation is a great way to improve the frame rates for app-based animations but its use is not a guarantee
of improved performance. Especially in OS X, you must still make choices about the most effective way to use
Core Animation behaviors. And as with all performance-related issues, you should use Instruments to measure
and track the performance of your app over time so that you can ensure that performance is improving and
not regressing.
For more information on view redraw policies, see The Layer Redraw Policy for OS X Views Affects
Performance (page 40).
For information about the different paths for rendering, including those that involve the updateLayer method,
see Using a Delegate to Provide the Layer’s Content (page 31).
74
Improving Animation Performance
General Tips and Tricks
One way to minimize drawing time for shape layers is to break up complex shapes into simpler shapes. Using
simpler paths and layering multiple CAShapeLayer objects on top of one another in the compositor can be
much faster than drawing one large complex path. That is because the drawing operations happen on the
CPU whereas compositing takes place on the GPU. As with any simplifications of this nature, though, the
potential performance gains are dependent on your content. Therefore, it is especially important to measure
the performance of your code before optimizing so that you have a baseline to use for comparisons.
75
Improving Animation Performance
General Tips and Tricks
76
Layer Style Property Animations
Objective-CSwift
During the rendering process, Core Animation takes different attributes of the layer and renders them in a
specific order. This order determines the final appearance of the layer. This chapter illustrates the rendered
results achieved by setting different layer style properties.
Note: The layer style properties available on Mac OS X and iOS differ and are noted throughout this
chapter.
Geometry Properties
A layer’s geometry properties specify how it is displayed relative to its parent layer. The geometry also specifies
the radius used to round the layer corners and a transform that is applied to the layer and its sublayers. Figure
A-1 shows the bounding rectangle of the example layer.
77
Layer Style Property Animations
Background Properties
● anchorPoint
● cornerRadius
● transform
● zPosition
iOS Note: The cornerRadius property is supported only in iOS 3.0 and later.
Background Properties
The first thing Core Animation renders is the layer’s background. You can specify a color for the background.
In OS X, you can also specify a Core Image filter that you want to apply to the background content. Figure A-2
shows two versions of a sample layer. The layer on the left has its backgroundColor property set while the
layer on the right has no background color but does have a border some content and a pinch distortion filter
assigned to its backgroundFilters property.
The background filter is applied to the content that lies behind the layer, which primarily consists of the parent
layer’s content. You might use a background filter to make the foreground layer content stand out; for example,
by applying a blur filter.
78
Layer Style Property Animations
Layer Content
Platform Note: In iOS, the backgroundFilters property is exposed in the CALayer class but the
filters you assign to this property are ignored.
Layer Content
If the layer has any content, that content is rendered on top of the background color. You can provide layer
content by setting a bitmap directly, by using a delegate to specify the content, or by subclassing the layer
and drawing the content directly. And you can use many different drawing technologies (including Quartz,
Metal, OpenGL, and Quartz Composer) to provide that content. Figure A-3 shows a sample layer whose contents
are a bitmap that was set directly. The bitmap content consists of a largely transparent space with the Automator
icon in the lower right corner.
Layers with a corner radius do not automatically clip their contents; however, setting the layer’s masksToBounds
property to YES does cause the layer to clip to its corner radius.
79
Layer Style Property Animations
Sublayers Content
Sublayers Content
Any layer may contain one or more child layers, known as sublayers. Sublayers are rendered recursively and
positioned relative to the parent layer's bounds rectangle. In addition, Core Animation applies the parent layer’s
sublayerTransform to each sublayer relative to the parent layer’s anchor point. You can use the sublayer
transform to apply perspective and other effects to all of the layers equally. Figure A-4 shows a sample layer
with two sublayers. The version on the left includes a background color while the version on the right does
not.
Setting the masksToBounds property of a layer to YES causes any sublayers to be clipped to the bounds of
the layer.
80
Layer Style Property Animations
Border Attributes
Border Attributes
A layer can display an optional border using a specified color and width. The border follows the bounds
rectangle of the layer and takes into account any corner radius values. Figure A-5 shows a sample layer after
applying a border. Notice that content and sublayers that are outside the layer’s bounds are rendered underneath
the border.
81
Layer Style Property Animations
Filters Property
Platform Note: The borderColor and borderWidth properties are supported only in iOS 3.0 and
later.
Filters Property
In OS X, you may apply one or more filters to the layer’s content and use a custom compositing filter to specify
how the layer’s contents blend with the content of its underlying layer. Figure A-6 shows a sample layer with
the Core Image posterize filter applied.
Platform Note: In iOS, layers ignore any filters you assign to them.
Shadow Properties
Layers can display shadow effects and configure their shape, opacity, color, offset, and blur radius. If you do
not specify a custom shadow shape, the shadow is based on the portions of the layer that are not fully
transparent. Figure A-7 shows several different versions of the same sample layer with a red shadow applied.
82
Layer Style Property Animations
Shadow Properties
The left and middle versions include a background color so the shadow appears only around the border of
the layer. However, the version on the right does not include a background color. In this case, the shadow is
applied to the layer’s content, border, and sublayers.
83
Layer Style Property Animations
Opacity Property
Opacity Property
The opacity property of a layer determines how much background content shows through the layer. Figure
A-8 shows a sample layer whose opacity is set to 0.5. This allows portions of the background image to show
through.
Mask Properties
You can use a mask to obscure all or part of a layer’s contents. The mask is itself a layer object whose alpha
channel is used to determine what is blocked and what is transmitted. Opaque portions of the mask layer’s
contents allow the underlying layer content to show through while transparent portions partially or fully
obscure the underlying content. Figure A-9 shows a sample layer composited with a mask layer and two
84
Layer Style Property Animations
Mask Properties
different backgrounds. In the left version, the layer’s opacity is set to 1.0. In the right version, the layer’s opacity
is set to 0.5, which increases the amount of background content that is transmitted through the masked portion
of the layer.
Platform Note: The mask property is supported in iOS 3.0 and later.
85
Animatable Properties
Many of the properties in CALayer and CIFilter can be animated. This appendix lists those properties, along
with the animation used by default.
backgroundFilters Uses the default implied CATransition object, described in Table B-3 (page
88). Sub-properties of the filters are animated using the default implied
CABasicAnimation object, described in Table B-2 (page 88).
compositingFilter Uses the default implied CATransition object, described in Table B-3 (page
88). Sub-properties of the filters are animated using the default implied
CABasicAnimation object, described in Table B-2 (page 88).
86
Animatable Properties
CALayer Animatable Properties
frame This property is not animatable. You can achieve the same results by
animating the bounds and position properties.
87
Animatable Properties
CALayer Animatable Properties
Table B-2 lists the animation attributes for the default property-based animations.
Description Value
Class CABasicAnimation
Table B-3 lists the animation object configuration for default transition-based animations.
Description Value
Class CATransition
88
Animatable Properties
CIFilter Animatable Properties
For more information about these additions, see CIFilter Core Animation Additions .
89
Key-Value Coding Extensions
Core Animation extends the NSKeyValueCoding protocol as it pertains to the CAAnimation and CALayer
classes. This extension adds default values for some keys, expands wrapping conventions, and adds key path
support for CGPoint, CGRect, CGSize, and CATransform3D types.
You can also retrieve the value for arbitrary keys like you would retrieve the value for other key paths. For
example, to retrieve the value of the someKey path set previously, you would use the following code:
someKeyValue=[theLayer valueForKey:@"someKey"];
OS X Note: The CAAnimation and CALayer classes, which automatically archive any additional
keys that you set up for instances of those classes, support the NSCoding protocol.
90
Key-Value Coding Extensions
Wrapping Conventions
To provide a default value for a key, create a subclass of the desired class and override its
defaultValueForKey: method. Your implementation of this method should examine the key parameter
and return the appropriate default value. Listing C-1 shows a sample implementation of the
defaultValueForKey: method for a layer object that provides a default value for the masksToBounds
property.
+ (id)defaultValueForKey:(NSString *)key
if ([key isEqualToString:@"masksToBounds"])
return [NSNumber numberWithBool:YES];
Wrapping Conventions
When the data for a key consists of a scalar value or C data structure, you must wrap that type in an object
before assigning it to the layer. Similarly, when accessing that type, you must retrieve an object and then
unwrap the appropriate values using the extensions to the appropriate class. Table C-1 lists the C types
commonly used and the Objective-C class you use to wrap them.
CGPoint NSValue
CGSize NSValue
CGRect NSValue
CATransform3D NSValue
91
Key-Value Coding Extensions
Key Path Support for Structures
rotation.x Set to an NSNumber object whose value is the rotation, in radians, in the x axis.
rotation.y Set to an NSNumber object whose value is the rotation, in radians, in the y axis.
rotation.z Set to an NSNumber object whose value is the rotation, in radians, in the z axis.
rotation Set to an NSNumber object whose value is the rotation, in radians, in the z axis.
This field is identical to setting the rotation.z field.
scale.x Set to an NSNumber object whose value is the scale factor for the x axis.
scale.y Set to an NSNumber object whose value is the scale factor for the y axis.
scale.z Set to an NSNumber object whose value is the scale factor for the z axis.
scale Set to an NSNumber object whose value is the average of all three scale factors.
translation.x Set to an NSNumber object whose value is the translation factor along the x axis.
translation.y Set to an NSNumber object whose value is the translation factor along the y axis.
translation.z Set to an NSNumber object whose value is the translation factor along the z axis.
translation Set to an NSValue object containing an NSSize or CGSize data type. That data
type indicates the amount to translate in the x and y axis.
92
Key-Value Coding Extensions
Key Path Support for Structures
The following example shows how you can modify a layer using the setValue:forKeyPath: method. The
example sets the translation factor for the x axis to 10 points, causing the layer to shift by that amount along
the indicated axis.
Note: Setting values using key paths is not the same as setting them using Objective-C properties.
You cannot use property notation to set transform values. You must use the setValue:forKeyPath:
method with the preceding key path strings.
93
Key-Value Coding Extensions
Key Path Support for Structures
94
Document Revision History
Date Notes
2010-09-24 Updated the document to reflect Core Animation support in iOS 4.2.
2010-08-12 Corrected iOS origin information. Clarified that the coordinate system
origin used in the examples are based on the OS X model.
95
Document Revision History
Date Notes
96
Apple Inc.
Copyright © 2015 Apple Inc.
All rights reserved.