CoreAnimation Guide PDF
CoreAnimation Guide PDF
CoreAnimation Guide PDF
Programming Guide
Contents
Contents
Contents
Animatable Properties 86
CALayer Animatable Properties 86
CIFilter Animatable Properties 89
Contents
Layer geometry 77
Layer with background color 78
Layer displaying a bitmap image 79
Layer displaying the sublayers content 80
Layer displaying the border attributes content 81
Layer displaying the filters properties 82
Layer displaying the shadow properties 83
Layer including the opacity property 84
Layer composited with the mask property 85
Animatable Properties 86
Table B-1
Table B-2
Table B-3
Table C-2
Table C-3
Table C-4
Table C-5
Listing C-1
SwiftObjective-C
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 apps views and give you more
fine-grained control over your apps 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 apps infrastructure.
10
11
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
Objective-CSwift
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 apps 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 apps 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 apps 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 views 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 views content around the screen, fade that content in or out, apply arbitrary graphics transformations to
the view, or change the views other visual attributes.
13
When a change triggers an animation, Core Animation passes the layers 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.
Figure 1-1
App Window
App Window
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 views
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 Layers Contents (page 30).
Layer-Based Animations
The data and state information of a layer object is decoupled from the visual presentation of that layers 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 layers position property causes Core Animation
14
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).
Figure 1-2
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
OS X
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 layers 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 layers size changes. You
can think of the unit coordinates as specifying a percentage of the total possible value. Every coordinate in
16
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
OS X
Note: Until OS X 10.8, the geometryFlipped property was a way to change the default orientation
of a layers 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
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 layers bounds origin changes the value in the position
property.
Figure 1-5
OS X
18
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.
Figure 1-6
OS X
19
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-7
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
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.
Figure 1-8
For information about the functions you use to create and manipulate transforms, see Core Animation Function
Reference .
Objects in the model layer tree (or simply layer tree) are the ones your app interacts with the most. The
objects in this tree are the model objects that store the target values for any animations. Whenever you
change the property of a layer, you use one of these objects.
Objects in the presentation tree contain the in-flight values for any running animations. Whereas the layer
tree objects contain the target values for an animation, the objects in the presentation tree reflect the
current values as they appear onscreen. You should never modify the objects in this tree. Instead, you use
these objects to read current animation values, perhaps to create a new animation starting at those values.
Objects in the render tree perform the actual animations and are private to Core Animation.
21
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 objectsthat is, layers not associated with a viewinto the
layer hierarchy as needed. You might do this in situations to optimize your apps 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.
Figure 1-9
22
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.
Figure 1-10
Display
Application
Layer Tree
Presentation Tree
Framework
Render Tree
23
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 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
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 apps 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
Objective-CSwift
Layer objects are at the heart of everything you do with Core Animation. Layers manage your apps 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 apps layers to get the effects you want.
Link against the QuartzCore framework. (iOS apps must link against this framework only if they use Core
Animation interfaces explicitly.)
Enable layer support for one or more of your NSView objects by doing one of the following:
In your nib files, use the View Effects inspector to enable layer support for your views. The inspector
displays checkboxes for the selected view and its subviews. It is recommended that you enable layer
support in the content view of your window whenever possible.
For views you create programmatically, call the views setWantsLayer: method and pass a value
of YES to indicate that the view should use layers.
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
Your view draws content using Metal or OpenGL ES, in which case you would use a CAMetalLayer or
CAEAGLLayer object.
You want to take advantage of some specialized Core Animation layer classes, such as particle emitters
or replicators.
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 views layer object cannot be changed.
Listing 2-1
+ (Class) layerClass {
return [CAMetalLayer class];
}
For a list of layer classes and how you use them, see Different Layer Classes Provide Specialized Behaviors (page
29).
27
// Create myView...
[myView setWantsLayer:YES];
CATiledLayer* hostedLayer = [CATiledLayer layer];
[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
Class
Usage
CAEmitterLayer
CAGradientLayer
Used to draw a color gradient that fills the shape of the layer
(within the bounds of any rounded corners).
CAMetalLayer
CAEAGLLayer/CAOpenGLLayer
Used to set up the backing store and context for rendering layer
content using OpenGL ES (iOS) or OpenGL (OS X).
CAReplicatorLayer
CAScrollLayer
CAShapeLayer
CATextLayer
CATiledLayer
CATransformLayer
29
Class
Usage
QCCompositionLayer
Assign an image object directly to the layer objects contents property. (This technique is best for layer
content that never, or rarely, changes.)
Assign a delegate object to the layer and let the delegate draw the layers content. (This technique is best
for layer content that might change periodically and can be provided by an external object, such as a
view.)
Define a layer subclass and override one of its drawing methods to provide the layer contents yourself.
(This technique is appropriate if you have to create a custom layer subclass anyway or if you want to
change the fundamental drawing behavior of the layer.)
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.
30
If your delegate implements the displayLayer: method, that implementation is responsible for creating
a bitmap and assigning it to the layers contents property.
If your delegate implements the drawLayer:inContext: method, Core Animation creates a bitmap,
creates a graphics context to draw into that bitmap, and then calls your delegate method to fill the bitmap.
All your delegate method has to do is draw into the provided graphics context.
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.
Listing 2-3
- (void)displayLayer:(CALayer *)theLayer {
// Check the value of some state property
if (self.displayYesImage) {
// Display the Yes image
theLayer.contents = [someHelperObject loadStateYesImage];
}
else {
// Display the No image
theLayer.contents = [someHelperObject loadStateNoImage];
}
}
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
Listing 2-4
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);
For layer-backed views with custom content, you should continue to override the views 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 views
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 layers contents
property. This is the one scenario where AppKit expects you to set the contents of a views layer object directly.
32
Override the layers display method and use it to set the contents property of the layer directly.
Override the layers 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 layers 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 position-based gravity constants allow you to pin your image to a particular edge or corner of the
layers 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 layers
bounds rectangle. The kCAGravityCenter constant centers the image in the layer. None of these constants
33
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 layers 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 layers background color, if set.
Figure 2-1
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 images original aspect ratio. Some modes preserve it and others do not. By default, a
layers contentsGravity property is set to the kCAGravityResize constant, which is the only mode that
does not preserve the image aspect ratio.
Figure 2-2
34
35
Listing 2-5 shows the code needed to set the background color and border for a layer. All of these properties
are animatable.
Listing 2-5
36
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 layers background color to an opaque color, consider setting the layers opaque property to
YES. Doing so can improve performance when compositing the layer onscreen and eliminates the need for
the layers 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
OS X
When adding shadows to a layer, the shadow is part of the layers content but actually extends outside the
layers 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
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
layers 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 layers foreground content only.
The backgroundFilters property contains an array of filters that affect the layers background content
only.
The compositingFilter property defines how the layers 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 layers setValue:forKeyPath: method to change filter values after the fact.
39
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 layers image is used
automatically.
Listing 2-6
For information about the available Core Image filters, see Core Image Filter Reference .
40
Table 2-2
Policy
Usage
NSViewLayerContentsRedrawOnSetNeedsDisplay
This is the recommended policy. With this policy, view geometry changes
do not automatically cause the view to update its layers contents. Instead,
the layers existing contents are stretched and manipulated to facilitate
the geometry changes. To force the view to redraw itself and update the
layers contents, you must explicitly call the views 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.
NSViewLayerContentsRedrawDuringViewResize
NSViewLayerContentsRedrawBeforeViewResize
With this policy, AppKit draws the layer at its final size prior to any resize
operations and caches that bitmap. The resize operation uses the cached
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
views 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.
NSViewLayerContentsRedrawNever
With this policy, AppKit does not update the layer at all, even when you
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 views 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 views redraw
policy to an appropriate value, rather than creating explicit sublayer hierarchies.
41
42
SwiftObjective-C
The infrastructure provided by Core Animation makes it easy to create sophisticated animations of your apps
layers, and by extension to any views that own those layers. Examples include changing the size of a layers
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).
43
Listing 3-1
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.
Listing 3-2
// 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 layers 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 objects 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 layers 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
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).
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.
Listing 3-3
45
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;
For properties that take a CGRect (such as the bounds and frame properties), wrap each rectangle in an
NSValue object.
For the layers 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 layers contents property, specify an array of CGImageRef data types.
46
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.
The calculationMode property defines the algorithm to use in calculating the animation timing. The
value of this property affects how the other timing-related properties are used.
Linear and cubic animationsthat is, animations where the calculationMode property is set to
kCAAnimationLinear or kCAAnimationCubicuse the provided timing information to generate
the animation. These modes give you the maximum control over the animation timing.
The keyTimes property specifies time markers at which to apply each keyframe value. This property is
used only if the calculation mode is set to kCAAnimationLinear, kCAAnimationDiscrete, or
kCAAnimationCubic. It is not used for paced animations.
The timingFunctions property specifies the timing curves to use for each keyframe segment. (This
property replaces the inherited timingFunction property.)
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
To remove a single animation object from the layer, call the layers removeAnimationForKey: method
to remove your animation object. This method uses the key that was passed to the
addAnimation:forKey: method to identify the animation. The key you specify must not be nil.
To remove all animation objects from the layer, call the layers removeAllAnimations method. This
method removes all ongoing animations immediately and redraws the layer using its current state
information.
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 layers 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).
// Animation 1
CAKeyframeAnimation* widthAnim = [CAKeyframeAnimation
animationWithKeyPath:@"borderWidth"];
NSArray* widthValues = [NSArray arrayWithObjects:@1.0, @10.0, @5.0, @30.0, @0.5,
@15.0, @2.0, @50.0, @0.0, nil];
48
widthAnim.values = widthValues;
widthAnim.calculationMode = kCAAnimationPaced;
// Animation 2
CAKeyframeAnimation* colorAnim = [CAKeyframeAnimation
animationWithKeyPath:@"borderColor"];
NSArray* colorValues = [NSArray arrayWithObjects:(id)[UIColor greenColor].CGColor,
(id)[UIColor redColor].CGColor, (id)[UIColor blueColor].CGColor,
nil];
colorAnim.values = colorValues;
colorAnim.calculationMode = kCAAnimationPaced;
// Animation group
CAAnimationGroup* group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:colorAnim, widthAnim, nil];
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).
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
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).
50
anchorPoint
bounds
compositingFilter
filters
frame
geometryFlipped
hidden
position
shadowColor
shadowOffset
shadowOpacity
shadowRadius
transform
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 views 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
52
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.
Behavior
Methods
Description
Adding
layers
addSublayer:
53
Behavior
Methods
Description
Inserting
layers
insertSublayer:
above:
insertSublayer:
atIndex:
insertSublayer:
below:
Removing
layers
removeFromSuperlayer
Exchanging
layers
replaceSublayer:
with:
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.
54
Important: Always use integral numbers for the width and height of your layer.
Create one or more CAConstraint objects. Use those objects to define the constraint parameters.
2.
Add your constraint objects to the layer whose attributes they modify.
3.
Retrieve the shared CAConstraintLayoutManager object and assign to the immediate superlayer.
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
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 layers size and position very precisely
using a simple set of rules.
Figure 4-1
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 layers right edge changes. If you specify a single constraint for one of the layers 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:
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 layers
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
Listing 4-1
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.
Figure 4-2
Listing 4-2
// Create and set a constraint layout manager for the parent layer.
theLayer.layoutManager=[CAConstraintLayoutManager layoutManager];
57
// Position the top edge of layerB 10 points from the bottom edge of layerA.
[layerB addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxY
relativeTo:@"layerA"
attribute:kCAConstraintMinY
58
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.
59
60
The shape of a layers clipping mask includes the layers 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.
Figure 4-3
convertPoint:fromLayer:
convertPoint:toLayer:
convertRect:fromLayer:
convertRect:toLayer:
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
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
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.
63
transition.subtype = kCATransitionFromRight;
transition.duration = 1.0;
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.
Listing 5-2
[self.imageView2 setHidden:NO];
[self.imageView.layer addAnimation:transition forKey:@"transition"];
64
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.
65
Once you have a time value in the layers 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 animations 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 {
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime()
fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer timeOffset];
66
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime()
fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
[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.
Listing 5-6
[CATransaction begin];
67
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.
Listing 5-7
68
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
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 apps layer objects.
The value of one of the layers properties changed. This can be any of the layers 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
If the layer has a delegate and that delegate implements the actionForLayer:forKey: method, the
layer calls that method. The delegate must do one of the following:
Return nil if it does not handle the action, in which case the search continues.
Return the NSNull object, in which case the search ends immediately.
2.
The layer looks for the given key in the layers actions dictionary.
3.
The layer looks in the style dictionary for an actions dictionary that contains the key. (In other word, the
style dictionary contains an actions key whose value is also a dictionary. The layer looks for the given
key in this second dictionary.)
4.
5.
The layer performs the implicit action (if any) defined by Core Animation.
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 objects
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 objects 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 layers actions dictionary.
For actions related to custom properties that you define on the layer object, include the action in the
layers style dictionary.
For actions that are fundamental to the behavior of the layer, subclass the layer and override the
defaultActionForKey: method.
71
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 layers contents property and swaps the new contents into place using a
transition animation.
Listing 6-1
- (id<CAAction>)actionForLayer:(CALayer *)theLayer
forKey:(NSString *)theKey {
CATransition *theAnimation=nil;
if ([theKey isEqualToString:@"contents"]) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
[aLayer removeFromSuperlayer];
72
[CATransaction commit];
For more information about using transaction objects to manage animation behavior, see Explicit Transactions
Let You Change Animation Parameters (page 67).
73
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.
74
75
76
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 layers 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.
Figure A-1
Layer geometry
bounds
position
frame (computed from the bounds and position and is not animatable)
77
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 layers 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.
Figure A-2
The background filter is applied to the content that lies behind the layer, which primarily consists of the parent
layers content. You might use a background filter to make the foreground layer content stand out; for example,
by applying a blur filter.
The following CALayer properties affect the display of a layers background:
backgroundColor
78
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.
Figure A-3
Layers with a corner radius do not automatically clip their contents; however, setting the layers masksToBounds
property to YES does cause the layer to clip to its corner radius.
The following CALayer properties affect the display of a layers content:
contents
contentsGravity
masksToBounds
79
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 layers
sublayerTransform to each sublayer relative to the parent layers 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.
Figure A-4
Setting the masksToBounds property of a layer to YES causes any sublayers to be clipped to the bounds of
the layer.
The following CALayer properties affect the display of a layers sublayers:
sublayers
masksToBounds
sublayerTransform
80
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 layers bounds are rendered underneath
the border.
Figure A-5
borderColor
borderWidth
81
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 layers content and use a custom compositing filter to specify
how the layers contents blend with the content of its underlying layer. Figure A-6 shows a sample layer with
the Core Image posterize filter applied.
Figure A-6
filters
compositingFilter
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
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 layers content, border, and sublayers.
Figure A-7
shadowColor
shadowOffset
shadowOpacity
shadowRadius
shadowPath
83
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.
Figure A-8
opacity
Mask Properties
You can use a mask to obscure all or part of a layers 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 layers
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
different backgrounds. In the left version, the layers opacity is set to 1.0. In the right version, the layers opacity
is set to 0.5, which increases the amount of background content that is transmitted through the masked portion
of the layer.
Figure A-9
mask
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.
Property
Default animation
anchorPoint
backgroundColor
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).
borderColor
borderWidth
bounds
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).
contents
86
Animatable Properties
CALayer Animatable Properties
Property
Default animation
contentsRect
cornerRadius
doubleSided
filters
frame
This property is not animatable. You can achieve the same results by
animating the bounds and position properties.
hidden
mask
masksToBounds
opacity
position
shadowColor
shadowOffset
shadowOpacity
shadowPath
shadowRadius
87
Animatable Properties
CALayer Animatable Properties
Property
Default animation
sublayers
sublayerTransform
transform
zPosition
Table B-2 lists the animation attributes for the default property-based animations.
Table B-2
Description
Value
Class
CABasicAnimation
Duration
Key path
Table B-3 lists the animation object configuration for default transition-based animations.
Table B-3
Description
Value
Class
CATransition
Duration
Type
Fade (kCATransitionFade)
Start progress
0.0
End progress
1.0
88
Animatable Properties
CIFilter Animatable Properties
name
enabled
For more information about these additions, see CIFilter Core Animation Additions .
89
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
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.
Listing C-1
+ (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.
Table C-1
C type
Wrapping class
CGPoint
NSValue
CGSize
NSValue
CGRect
NSValue
CATransform3D
NSValue
CGAffineTransform
91
Description
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
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.
[myLayer setValue:[NSNumber numberWithFloat:10.0]
forKeyPath:@"transform.translation.x"];
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.
Structure Field
Description
Structure Field
Description
width
height
93
Structure Field
Description
origin
origin.x
origin.y
size
size.width
size.height
94
Date
Notes
2015-03-09
2013-01-28
2010-09-24
2010-08-12
2010-05-25
2010-03-24
2010-02-24
2010-01-20
2009-10-19
2009-08-13
2008-11-13
2008-09-09
Corrected typos.
95
Date
Notes
2008-06-18
2008-05-06
Corrected typos.
2008-03-11
Corrected typos.
2008-02-08
2007-12-11
Corrected typos.
2007-10-31
96
Apple Inc.
Copyright 2015 Apple Inc.
All rights reserved.
No part of this publication may be reproduced,
stored in a retrieval system, or transmitted, in any
form or by any means, mechanical, electronic,
photocopying, recording, or otherwise, without
prior written permission of Apple Inc., with the
following exceptions: Any person is hereby
authorized to store documentation on a single
computer or device for personal use only and to
print copies of documentation for personal use
provided that the documentation contains
Apples copyright notice.
No licenses, express or implied, are granted with
respect to any of the technology described in this
document. Apple retains all intellectual property
rights associated with the technology described
in this document. This document is intended to
assist application developers to develop
applications only for Apple-branded products.
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
408-996-1010
Apple, the Apple logo, Cocoa, Cocoa Touch,
Instruments, Mac, Mac OS, Objective-C, OS X, and
Quartz are trademarks of Apple Inc., registered
in the U.S. and other countries.
Retina is a trademark of Apple Inc.
IOS is a trademark or registered trademark of
Cisco in the U.S. and other countries and is used
under license.
OpenGL is a registered trademark of Silicon
Graphics, Inc.
Times is a registered trademark of Heidelberger
Druckmaschinen AG, available from Linotype
Library GmbH.
APPLE MAKES NO WARRANTY OR REPRESENTATION,
EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS
DOCUMENT, ITS QUALITY, ACCURACY,
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR
PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED
AS IS, AND YOU, THE READER, ARE ASSUMING THE
ENTIRE RISK AS TO ITS QUALITY AND ACCURACY.
IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES RESULTING FROM ANY DEFECT, ERROR OR
INACCURACY IN THIS DOCUMENT, even if advised of
the possibility of such damages.
Some jurisdictions do not allow the exclusion of
implied warranties or liability, so the above exclusion
may not apply to you.