At the WWDC 2013 Keynote, Apple's Senior Vice President of Design, Jony Ive, introduced the new interface changes for iOS 7. During his recorded video presentation he referred to the "importance of motion and depth" and "new approaches to animation."

Moving and tilting your device while viewing the Home screen is perhaps the most visible example of the focus on motion and depth. The device background will appear to adjust to suit your perspective, almost as if you are looking underneath the layer of icons. Apple calls this behavior Parallax and it's part of an idea called Motion Effects. The tabs in Mobile Safari have also been updated to look like pages in a stack, thus providing visual depth.

Apple has made it easier for developers to incorporate complex 2D animations through a new framework called UIKit Dynamics. While all of the animations discussed in this post are possible with existing view animations and with Core Animation, the new Dynamics framework adds a layer of abstraction to allow for a more declarative approach. You simply need to decide what it is you want to accomplish with your animations.

There is a great example in iOS 7 that highlight UIKit Dynamics - the new lock screen. On the "iOS 6 lock screen you can tap the camera icon and drag upwards to reveal the camera interface. Lifting your finger before reaching a certain point will cause the lock screen to softly fall back down to the bottom, returning to where it fully covers the camera screen. Performing the same action in iOS 7 will reveal a new behavior – the lock screen will slide down and collide with the bottom, bouncing until it comes to rest. In a sense, this behavior mimics dropping an object with mass and elasticity from a small height. This is a key component of UIKit Dynamics in that Apple has made it possible to incorporate real-world physics into the 2D animation.

Examples like the new lock screen are easily achieved with the new UIKit Dynamics framework, at the heart of which are three concepts – dynamic items, dynamic behaviors, and dynamic animators. Let's start by covering dynamic items.

This post is accompanied by a sample application that explores many of the concepts that follow.

Dynamic Items

The focus of UIKit Dynamics is all about the interactions between items and their animations. The one requirement, in order to bestow dynamic behavior on an item, is that the item must conform to the UIDynamicItem protocol. This protocol defines three vital properties that allow the UIKit Dynamics engine to track animation states over time: the bounds, center, and transform properties. Only the center property is read/write since it needs to be updated as the animation progresses. The transform property returns a CGAffineTransform object but only the rotation value is used.

By default, only the UIView and UICollectionViewLayoutAttributes classes implement the UIDynamicItem protocol. This is useful since most animations will likely involve one of these classes. However, you can still create a custom class that is eligible for animation with UIKit Dynamics, provided your class conforms to the UIDynamicItem protocol and exposes a bounds, center, and transform property.

Now, suppose you have a UIView or some other custom class worthy of dynamic animation. The next step is to decide what behaviors you want your dynamic item to exhibit.

Dynamic Behaviors

In UIKit Dynamics, a dynamic behavior represents a real world physical behavior that you can apply to your animation. There are six classes that provide all the behaviors you will need. They are:

  • UIAttachmentBehavior
  • UICollisionBehavior
  • UIGravityBehavior
  • UIPushBehavior
  • UISnapBehavior
  • UIDynamicItemBehavior (not a concrete behavior; allows customization of the various properties used in the other behaviors)

Any of these behaviors can be combined if they make sense, but note that it is possible to define behaviors that conflict with each other.

The Attachment Behavior

Use the UIAttachmentBehavior class to create an invisible connection between two items. The connection can be defined as one of the following:

  1. One dynamic item attached to another dynamic item, e.g. two UIViews
  2. One dynamic item attached to an anchor point, e.g. a UIView to a CGPoint

If two items are attached, one of the items is always the leader and the other the follower. If a dynamic item with an attachment behavior moves, any attached follower will also move (multiple dynamic items can be attached to a single dynamic item). The movement is constrained by a length property that is established when the attachment behavior is initialized. The length can be adjusted but only after the attachment behavior has been created.

When a dynamic item is attached to an anchor point, the behavior is much the same as a pendulum. The dynamic item, in this example represented by the moving end of the pendulum, can have motion in a fixed plane but it will never increase its distance from the pendulum's attached end, i.e. the anchor point.

In addition to the length and anchorPoint properties, you can also configure properties for damping and frequency of oscillation. Damping is configured with a value between 0.0f and 1.0f, with 0.0f being no effect at all and 1.0f representing the maximum effect. Apple's documentation states that the setting for frequency of oscillation is in hertz. For the attachment behavior, the default values for each are not specified.

Creating an attachment behavior is simple. You just need to identify the items you wish to connect.

<span class="co2">// Initialize a couple of UIView objects</span>
<span class="co2">// The UIView class already conforms to the UIDynamicItem protocol</span>
UIView <span class="sy0">*</span>v1 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIView alloc<span class="br0">]</span> initWithFrame<span class="sy0">:</span>CGRectMake<span class="br0">(</span>0.0f, 0.0f, 100.0f, 100.0f<span class="br0">)</span><span class="br0">]</span>;
UIView <span class="sy0">*</span>v2 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIView alloc<span class="br0">]</span> initWithFrame<span class="sy0">:</span>CGRectMake<span class="br0">(</span>200.0f, 0.0f, 100.0f, 100.0f<span class="br0">)</span><span class="br0">]</span>;
 
<span class="co2">// Create an attachment behavior between two dynamic items, v1 and v2</span>
UIAttachmentBehavior <span class="sy0">*</span>attachment1 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIAttachmentBehavior alloc<span class="br0">]</span> initWithItem<span class="sy0">:</span>v1 attachedToItem<span class="sy0">:</span>v2<span class="br0">]</span>;
 
<span class="co2">// Configure damping and frequency (of oscillation) properties for attachment1</span>
<span class="br0">[</span>attachment1 setDamping<span class="sy0">:</span>0.5f<span class="br0">]</span>;
<span class="br0">[</span>attachment1 setFrequency<span class="sy0">:</span>0.2f<span class="br0">]</span>;
 
<span class="co2">// Create an attachment behavior between a dynamic item and an anchor point, v2, and a CGPoint</span>
UIAttachmentBehavior <span class="sy0">*</span>attachment2 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIAttachmentBehavior alloc<span class="br0">]</span> initWithItem<span class="sy0">:</span>v2 
 attachedToAnchor<span class="sy0">:</span>CGPointMake<span class="br0">(</span>100.0f, 100.0f<span class="br0">)</span><span class="br0">]</span>;

Attachment behaviors are useful when the position of two items should exhibit a connected behavior. You can even chain attachments so that Item B follows Item A, and Item C follows Item B, and Item D follows Item C, and so on. There is a good example of this attachment behavior in iOS 7 – the scrolling action in the Chat application. As the message bubbles move up or down the screen you'll notice that they appear to be attached by invisible springs, first separating then catching up to each other. Each bubble reacts to the immediately preceding bubble, depending on which way you are scrolling.

The Collision Behavior

The UICollisionBehavior class provides the ability for dynamic items to participate in collisions with each other and/or any boundary you specify. A boundary can be any of the following:

  1. The reference bounds of the animation, which refers to the bounds of the view that contains the items that you wish to animate. The reference bounds are set when you initialize a dynamic animator (see example code below). This type of bounds defines a rectangular area that will contain your collisions
  2. The reference bounds of the animation with a specified inset, for when you wish to define a smaller boundary area inside an existing view.
  3. A line segment connected by two points which effectively defines an invisible wall that your dynamic items can collide with.
  4. A boundary defined by a Bezier path is also possible. For example, if you want a dynamic item to collide and slide in a curved path, you could use this type of boundary.

You create a collision behavior by adding dynamic items during initialization. By rule, only dynamic items that are added to the same collision behavior are able collide with each other, as well as any boundaries defined by the behavior. You determine whether your items should collide with their sibling items and boundaries by setting a property called collisionMode. There are three options that control the intended outcome:

  • UICollisionBehaviorModeEverything
  • UICollisionBehaviorModeBoundaries
  • UICollisionBehaviorModeItems

The default is UICollisionBehaviorModeEverything, which means the collision behavior's items will collide with each other as well as its configured boundaries. A setting of UICollisionBehaviorModeBoundaries results in the dynamic items colliding only with the behavior's boundaries, while UICollisionBehaviorModeItems limits the interaction to just the dynamic items.

Creating a collision behavior involves identifying the participating dynamic items, setting a reference bounds, and then setting a collision mode.

<span class="co2">// Suppose we already have a few UIViews that we want to participate in collisions</span>
<span class="co2">// v1, v2, v3, v4, v5, and v6</span>
<span class="co2">// Create a collision behavior and initialize with two of the views</span>
UICollisionBehavior <span class="sy0">*</span>collision1 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UICollisionBehavior alloc<span class="br0">]</span> initWithItems<span class="sy0">:</span>@<span class="br0">[</span>v1, v2<span class="br0">]</span><span class="br0">]</span>;
 
<span class="co2">// Set the bounds and collision mode = everything; v1 and v2 will collide with each other and its boundaries</span>
<span class="br0">[</span>collision1 setTranslatesReferenceBoundsIntoBoundary<span class="sy0">:</span><span class="kw2">YES</span><span class="br0">]</span>;
<span class="br0">[</span>collision1 setCollisionMode<span class="sy0">:</span>UICollisionBehaviorModeEverything<span class="br0">]</span>;
 
<span class="co2">// Create a second collision behavior</span>
UICollisionBehavior <span class="sy0">*</span>collision2 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UICollisionBehavior alloc<span class="br0">]</span> initWithItems<span class="sy0">:</span>@<span class="br0">[</span>v3, v4<span class="br0">]</span><span class="br0">]</span>;
 
<span class="co2">// Set the bounds and collision mode = other items only; v3 and v4 will collide only with each other</span>
<span class="br0">[</span>collision2 setTranslatesReferenceBoundsIntoBoundary<span class="sy0">:</span><span class="kw2">YES</span><span class="br0">]</span>;
<span class="br0">[</span>collision2 setCollisionMode<span class="sy0">:</span>UICollisionBehaviorModeItems<span class="br0">]</span>;
 
<span class="co2">// And a third collision behavior...</span>
UICollisionBehavior <span class="sy0">*</span>collision3 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UICollisionBehavior alloc<span class="br0">]</span> initWithItems<span class="sy0">:</span>@<span class="br0">[</span>v5, v6<span class="br0">]</span><span class="br0">]</span>;
 
<span class="co2">// Set the bounds and collision mode = only boundaries; v5 and v6 will collide only with it boundaries</span>
<span class="br0">[</span>collision3 setTranslatesReferenceBoundsIntoBoundary<span class="sy0">:</span><span class="kw2">YES</span><span class="br0">]</span>;
<span class="br0">[</span>collision3 setCollisionMode<span class="sy0">:</span>UICollisionBehaviorModeBoundaries<span class="br0">]</span>;

In the preceding example, the items added to collision1 will never collide with items in the collision2 and collision3 behaviors, only each other. It is also important to note that a single dynamic item can be associated with multiple collision behaviors, provided those behaviors are managed by the same dynamic animator (more on dynamic animators later in this post).

There are multiple delegate callbacks that indicate when an item begins or ends contact with another item or boundary – you simply conform to UICollisionBehaviorDelegate and set the collisionDelegate property of your behavior.

In the following example, we respond to the end of a collision. In this case, we do a quick check to make sure the item is what we expect it to be, and then write a simple message to the console. Recall that the reference bounds for our sample collision behaviors used setTranslatesReferenceBoundsIntoBoundary:YES. Because of this, the identifier parameter will be nil. In order to have an identifier you must explicitly create a line segment or Bezier path boundary. The initializers for both require that you provide an identifier parameter.

<span class="sy0">-</span> <span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>collisionBehavior<span class="sy0">:</span><span class="br0">(</span>UICollisionBehavior <span class="sy0">*</span><span class="br0">)</span>behavior endedContactForItem<span class="sy0">:</span><span class="br0">(</span>id<span class="br0">)</span>item 
 withBoundaryIdentifier<span class="sy0">:</span><span class="br0">(</span>id<span class="br0">)</span>identifier <span class="br0">{</span>
 
 <span class="co2">// Print a description of the item that collided, if it's one of our UIViews</span>
 <span class="kw1">if</span> <span class="br0">(</span><span class="br0">[</span>item isKindOfClass<span class="sy0">:</span><span class="br0">[</span>UIView class<span class="br0">]</span><span class="br0">]</span><span class="br0">)</span> <span class="br0">{</span>
 NSLog<span class="br0">(</span><span class="co3">@</span><span class="st0">"end collision for item: %@"</span>, item.description<span class="br0">)</span>;
 <span class="br0">}</span>
<span class="br0">}</span>

Keep in mind that for any collision boundaries, you must ensure that the starting position of your dynamic items does not intersect with that boundary. If you don't check this, the resulting animation will be unpredictable.

Most of the behaviors permit us to add and remove items at any time. The collision behavior is one of these. All behaviors that allow this action will expose the same methods.

<span class="co2">// Remove an item</span>
<span class="br0">[</span>collision1 removeItem<span class="sy0">:</span>v2<span class="br0">]</span>;
 
<span class="co2">// Add it back</span>
<span class="br0">[</span>collision1 addItem<span class="sy0">:</span>v2<span class="br0">]</span>;

At the beginning of this post, I shared an example that employs a really effective collision implementation: the new iOS 7 Lock screen. Another great example is when you use a swipe gesture to pull down the Notification Center. In each of these examples, you release the gesture and there is a subsequent collision with the bottom of the screen. In the Lock screen, the collision is softer. The Notification Center provides a variable interaction – the quicker or more forcefully you gesture downwards before removing your tap, the more impact you will see with the bottom of the screen. This also results in more bounce.

Collisions are a nice addition when you need to present another view based on user gestures. Not only does it give a sense of control to the user, it gives the incoming view a sense of momentum. I highly recommend using collisions in this way to spice up your transitions and to add some weight to your views.

The Gravity Behavior

No set of physics behaviors is complete without a little gravity. In UIKit Dynamics, the UIGravityBehavior class allows you to implement Sir Isaac Newton's favorite attractive force.

A directional vector and an acceleration value are used to model gravity within UIKit Dynamics. The default directional vector, set in the gravityDirection property, is towards the bottom of the device's screen with no left or right movement, and is defined by an x value = 0.0f and and a y value = 1.0f. A y value of 1.0f signals that the acceleration is downwards at 1000 points per second^2, known as standard UIKit Gravity. Setting x or y to a negative value changes the direction. Also, setting either value to 0.5f results in an acceleration vector of 500 points per second^2 instead of the default 1000.

<span class="co2">// Create a gravity behavior</span>
UIGravityBehavior <span class="sy0">*</span>gravity1 <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIGravityBehavior alloc<span class="br0">]</span> initWithItems<span class="sy0">:</span>@<span class="br0">[</span>v1<span class="br0">]</span><span class="br0">]</span>;
 
<span class="co2">// Set gravity to move downwards at 500 points per second^2</span>
<span class="br0">[</span>gravity1 setGravityDirection<span class="sy0">:</span>CGVectorMake<span class="br0">(</span><span class="nu0">0.0</span>, <span class="nu0">0.5</span><span class="br0">)</span><span class="br0">]</span>;
 
<span class="co2">// Set gravity to move left at 500 and upwards at 900 points per second^2</span>
<span class="br0">[</span>gravity1 setGravityDirection<span class="sy0">:</span>CGVectorMake<span class="br0">(</span><span class="sy0">-</span><span class="nu0">0.5</span>, <span class="sy0">-</span><span class="nu0">0.9</span><span class="br0">)</span><span class="br0">]</span>;

You can also configure the directional and acceleration vectors using the angle and magnitude properties. Each of these properties must be set together to properly configure a gravity vector. That is, if one is defined, the other must also be defined. The angle property is in radians. The magnitude property defaults to 1.0f.

<span class="co2">// Set a magnitude and angle instead</span>
<span class="br0">[</span>gravity1 setAngle<span class="sy0">:</span><span class="nu0">0.0</span> magnitude<span class="sy0">:</span><span class="nu0">0.5</span><span class="br0">]</span>;

The gravity behavior is fairly simplistic. Once you apply gravity to an item, it will head off in the direction of the configured vector, continuing along its path until some other behavior causes it to stop - or until you programmatically remove the item from the behavior or remove the behavior itself. For this reason, a gravity behavior will usually be coupled with some other behavior to influence the animation. For example, coupling gravity with collision can ensure that your item stops moving when it contacts a collision boundary. Otherwise, your item will fall off the screen. In the new iOS 7 Lock screen, ending the swipe-up gesture short of a certain point triggers the addition of gravity and collision behaviors, which causes the Lock screen to fall back down until it collides with the bottom of the screen. Just like the collision behavior, gravity is useful when used with view transitions, especially when there is some influence imparted by user gestures. If you are controlling a transition with a gesture, and that gesture ends prematurely, employing gravity and collision is a great way to visually return the transition to its starting point.

The Push Behavior

The UIPushBehavior class provides for either a "continuous or instantaneous" force that is applied to one or multiple dynamic items. You must initialize the push behavior mode (UIPushBehaviorMode), which can be one of the following:

  • UIPushBehaviorContinuousMode
  • UIPushBehaviorInstantaneousMode

With continuous mode, the object will gradually pick up speed after it is pushed. Instantaneous mode means the object starts at peak speed immediately after the push. Choosing between the two depends on what you're trying to achieve in the animation. If your dynamic items needs to exhibit mass and density, you should use the continuous mode. If not, instantaneous mode is the way to go.

Just like the gravity behavior, there is an angle and magnitude associated with push behaviors. When this behavior is first instantiated the magnitude is nil, meaning there is no force at all. Your dynamic item won't move anywhere until you supply a magnitude. A push behavior's magnitude is represented by the UIKit Newton, described in the Apple developer documentation as "A continuous force vector with a magnitude of 1.0, applied to a 100 point x 100 point view whose density value is 1.0, results in view acceleration of 100 points / second² in the direction of the vector." The angle property is defined in radians.

<span class="co2">// Create a push behavior with two UIViews and a continuous 'push' mode</span>
UIPushBehavior <span class="sy0">*</span>push <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIPushBehavior alloc<span class="br0">]</span> initWithItems<span class="sy0">:</span>@<span class="br0">[</span>v1, v2<span class="br0">]</span> mode<span class="sy0">:</span>UIPushBehaviorModeContinuous<span class="br0">]</span>;
 
<span class="co2">// Set an angle and magnitude</span>
<span class="br0">[</span>push setAngle<span class="sy0">:</span><span class="nu0">0.2</span> magnitude<span class="sy0">:</span><span class="nu0">0.5</span><span class="br0">]</span>;

Configuring a pushDirection is also an option:

<span class="kw1">@property</span><span class="br0">(</span>readwrite, nonatomic<span class="br0">)</span> CGVector pushDirection

By default, the push force is applied to the center of your dynamic item. You can specify an offset if you wish to direct the push force elsewhere on your item. Specifying an offset will effectively add angular momentum to your dynamic item, e.g. it will start spinning. This effect is easy to visualize; pushing on the corner of a box will direct a force that influences the box to rotate.

<span class="sy0">-</span> <span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>setTargetOffsetFromCenter<span class="sy0">:</span><span class="br0">(</span>UIOffset<span class="br0">)</span>o forItem<span class="sy0">:</span><span class="br0">(</span>id<span class="sy0">&</span>lt;uidynamicitem<span class="sy0">&</span>gt;<span class="br0">)</span>item

Like gravity behaviors, you can push your item off the screen unless you do something to intervene. When I described the involvement of gravity in the new Lock screen slide-up gesture, the view returned and collided with the bottom of the screen if the gesture ended short of a specified point. A push behavior is added when the gesture ends past that specified point. Instead of returning and colliding with the bottom of the screen, the Lock screen will continue until it has been pushed upwards off the screen. Again, we have a great way to add some spice to gesture-driven transitions. Push behaviors can also be coupled with the next behavior to create some very interesting animations.

The Snap Behavior

Creating a UISnapBehavior object requires the least amount of setup of all the behaviors but the animation it provides is perhaps the most eye-catching. This behavior allows you to snap a dynamic item to a point on the screen, almost like there is a magnetic attraction. But that's not all you get – the snap behavior also allows you to specify a damping value that causes your dynamic item to oscillate and bounce around the intended ‘snap-to' point until it settles into place.

<span class="co2">// Create a snap behavior</span>
<span class="co2">// The default damping value is 0.5 which means there is medium oscillation</span>
UISnapBehavior <span class="sy0">*</span>snap <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UISnapBehavior alloc<span class="br0">]</span> initWithItem<span class="sy0">:</span>v1 snapToPoint<span class="sy0">:</span>CGPointMake<span class="br0">(</span>100.0f, 100.0f<span class="br0">)</span><span class="br0">]</span>;

The damping property can have a value of 0.0f (no oscillation) to 1.0f (maximum oscillation). 0.5f is the default value.

<span class="co2">// Damping = 0.0; no oscillation - the animation will appear as if the item is simply moving to another location</span>
<span class="br0">[</span>snap setDamping<span class="sy0">:</span><span class="nu0">0.0</span><span class="br0">]</span>;
 
<span class="co2">// Damping = 1.0; maximum oscillation - the item will exhibit heightened oscillation around the </span>
<span class="co2">// snapToPoint before settling to rest</span>
<span class="br0">[</span>snap setDamping<span class="sy0">:</span><span class="nu0">1.0</span><span class="br0">]</span>;

This behavior can be used to implement some creative animations. During one of the WWDC presentations for UIKit Dynamics, the presenter showed an example of the snap behavior that involved sorting photos. There was a stack of items at the bottom of the screen that represented the photos. A couple of other screen locations contained stacks used to organize the images into categories. The images could be tapped and dragged via gesture, and once the tap gesture ended, the image would snap and settle into one of the category stacks, depending on where the gesture ended. In your application, perhaps you want to allow users to configure the layout of their content. A snap behavior would provide a nice interaction between content areas and the positioning of your content – simply dragging a ‘content pane' to another area would cause the panes to switch locations with a snap and slight oscillation. This type of animation is akin to common drag-and-drop functionality.

The Dynamic Item Behavior

Apple has included one more dynamic behavior that allows us to adjust the individual physical properties of a dynamic item. If we want to further define how an object should respond to a collision based on characteristics like mass and elasticity, the dynamic item behavior allows us to do so. We can also configure things like friction and resistance to slow down certain actions.

<span class="co2">// Initialize a dynamic item behavior</span>
<span class="co2">// v1 and v2 are instances of UIView</span>
UIDynamicItemBehavior <span class="sy0">*</span>dynamicItemBehavior <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIDynamicItemBehavior alloc<span class="br0">]</span> initWithItems<span class="sy0">:</span>@<span class="br0">[</span>v1, v2<span class="br0">]</span><span class="br0">]</span>;

Then we can configure the characteristics of the items in the behavior.

<span class="co2">// The available properties we can set for a dynamic item behavior</span>
<span class="br0">[</span>dynamicItemBehavior setAllowsRotation<span class="sy0">:</span><span class="kw2">YES</span><span class="br0">]</span>;
<span class="br0">[</span>dynamicItemBehavior setDensity<span class="sy0">:</span><span class="nu0">1.0</span><span class="br0">]</span>;
<span class="br0">[</span>dynamicItemBehavior setElasticity<span class="sy0">:</span><span class="nu0">1.0</span><span class="br0">]</span>;
<span class="br0">[</span>dynamicItemBehavior setFriction<span class="sy0">:</span><span class="nu0">0.2</span><span class="br0">]</span>;
<span class="br0">[</span>dynamicItemBehavior setResistance<span class="sy0">:</span><span class="nu0">0.0</span><span class="br0">]</span>;
<span class="br0">[</span>dynamicItemBehavior setAngularResistance<span class="sy0">:</span><span class="nu0">0.0</span><span class="br0">]</span>;

The density property directly relates to the effective mass of an object. Suppose we have two UIViews that are 100 x 100 points in size. If object A has a density of 1.0f (the default) and object B a density of 2.0f, object B will have two times the mass. Object B will act like the heavier object in a collision.

The elasticity property determines how elastic or bouncy the collision will be. This is usually a value between 0.0f and 1.0f but it can be higher. In practice, collisions that are bounded by a reference view can get ‘out of hand' if the value is greater than 1.0f because objects can actually pick up speed on the rebound, eventually becoming a blur.

The resistance and angularResistance properties are important because they allow you to slowly, or rapidly, remove velocity from an item. Without any resistance, an item with angular velocity will just spin forever, assuming it doesn't run into something that affects its rotation. Suppose we set the elasticity of an item to something greater than 1.0f – giving that item a little resistance could help to continually slow down its linear velocity, offsetting the motion blur I referred to.

In order to put the dynamic items in motion, we need to add linear or angular velocity, or both. Linear velocity is added to one dynamic item at a time and is translated into points per second.

<span class="br0">[</span>dynamicItemBehavior addLinearVelocity<span class="sy0">:</span>CGPointMake<span class="br0">(</span><span class="nu0">0.0</span>, <span class="nu0">100.0</span><span class="br0">)</span> forItem<span class="sy0">:</span>v1<span class="br0">]</span>;
<span class="br0">[</span>dynamicItemBehavior addLinearVelocity<span class="sy0">:</span>CGPointMake<span class="br0">(</span><span class="nu0">0.0</span>, <span class="sy0">-</span><span class="nu0">100.0</span><span class="br0">)</span> forItem<span class="sy0">:</span>v2<span class="br0">]</span>;

In the same way, we can add angular velocities to our items, translated into radians per second.

<span class="co2">// A positive value = clockwise spin; negative = counterclockwise</span>
<span class="br0">[</span>dynamicItemBehavior addAngularVelocity<span class="sy0">:</span><span class="nu0">10.0</span> forItem<span class="sy0">:</span>v1<span class="br0">]</span>;
<span class="br0">[</span>dynamicItemBehavior addAngularVelocity<span class="sy0">:-</span><span class="nu0">30.0</span> forItem<span class="sy0">:</span>v2<span class="br0">]</span>;

It is very easy to impart a velocity to objects in a dynamic item behavior. Because of that, Apple states that one "notable and common use of a dynamic item behavior is to confer a velocity to a dynamic item to match the ending velocity of a user gesture." For example, we can do the following:

<span class="co2">// Create a pan gesture recognizer</span>
UIPanGestureRecognizer <span class="sy0">*</span>panGestureRecognizer <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIPanGestureRecognizer alloc<span class="br0">]</span> initWithTarget<span class="sy0">:</span>self
action<span class="sy0">:</span><span class="kw1">@selector</span><span class="br0">(</span>handlePan<span class="sy0">:</span><span class="br0">)</span><span class="br0">]</span>;
 
<span class="co2">// Set gesture delegate</span>
<span class="br0">[</span>panGestureRecognizer setDelegate<span class="sy0">:</span>self<span class="br0">]</span>;
 
<span class="co2">// Add gesture to item v1</span>
<span class="br0">[</span>v1 setUserInteractionEnabled<span class="sy0">:</span><span class="kw2">YES</span><span class="br0">]</span>;
<span class="br0">[</span>v1 addGestureRecognizer<span class="sy0">:</span>panGestureRecognizer<span class="br0">]</span>;
 
<span class="co2">// Create gesture handler</span>
<span class="sy0">-</span> <span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>handlePan<span class="sy0">:</span><span class="br0">(</span>UIPanGestureRecognizer<span class="sy0">*</span><span class="br0">)</span>gesture <span class="br0">{</span>
 CGPoint translation <span class="sy0">=</span> <span class="br0">[</span>gesture translationInView<span class="sy0">:</span>gesture.view<span class="br0">]</span>;
 gesture.view.center <span class="sy0">=</span> CGPointMake<span class="br0">(</span>gesture.view.center.x <span class="sy0">+</span> translation.x, gesture.view.center.y
 <span class="sy0">+</span> translation.y<span class="br0">)</span>;
 <span class="br0">[</span>gesture setTranslation<span class="sy0">:</span>CGPointMake<span class="br0">(</span><span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">)</span> inView<span class="sy0">:</span>gesture.view<span class="br0">]</span>;
 
 <span class="co2">// Get the x and y velocities of the gesture</span>
 CGFloat xVelocity <span class="sy0">=</span> <span class="br0">[</span>gesture velocityInView<span class="sy0">:</span>gesture.view<span class="br0">]</span>.x;
 CGFloat yVelocity <span class="sy0">=</span> <span class="br0">[</span>gesture velocityInView<span class="sy0">:</span>gesture.view<span class="br0">]</span>.y;
 
 <span class="co2">// Impart a linear velocity through your dynamic item behavior</span>
 <span class="br0">[</span>dynamicItemBehavior addLinearVelocity<span class="sy0">:</span>CGPointMake<span class="br0">(</span>xVelocity, yVelocity<span class="br0">)</span> forItem<span class="sy0">:</span>v1<span class="br0">]</span>;
 
 <span class="co2">// The dynamic animator is discussed later</span>
 <span class="co2">// For now, animator is an instance of UIDynamicAnimator, used to add behaviors</span>
 <span class="br0">[</span>animator addBehavior<span class="sy0">:</span>dynamicItemBehavior<span class="br0">]</span>;
<span class="br0">}</span>

The Dynamic Animator

At the heart of UIKit Dynamics is the UIDynamicAnimator class. A dynamic animator object manages all of your dynamic behaviors by providing a context for all of your animations. It can be described as the layer that sits between the iOS physics engine and your dynamic behaviors. Its other responsibilities include updating the position of a dynamic item during animation and managing all the necessary rotations. This is accomplished by keeping track of the dynamic items' center, bounds, and transform properties, which is why all dynamic items must implement the UIDynamicItem protocol. The power of the UIDynamicAnimator class is easily overlooked because of its simplicity. All you have to do is add your behaviors and the dynamic animator handles the rest.

Before creating a dynamic animator object, you must first decide what it is you want to animate. Based on that decision, you will use one of two initializers:

  • initWithReferenceView:
  • initWithCollectionViewLayout:
<span class="co2">// Initialize the animator</span>
<span class="co2">// refView = the reference view that defines the animation context and coordinate system</span>
UIDynamicAnimator <span class="sy0">*</span>dynamicAnimator <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIDynamicAnimator alloc<span class="br0">]</span> initWithReferenceView<span class="sy0">:</span>self.refView<span class="br0">]</span>;

Providing a reference view or collection view layout sets the overall coordinate system that your dynamic animator will manage. All animations will occur within this specified coordinate system.

If you create your own dynamic item that conforms to the UIDynamicItem protocol, you can subclass UIDynamicBehavior and override the supplied init method. In this case the result will be an abstract coordinate system that does not rely on a specific screen or view.

After initializing your dynamic animator, you can begin adding dynamic behaviors by calling the addBehavior method. Calling the removeBehavior method will remove the dynamic behavior and it will no longer influence the animation. There is also an option to remove all dynamic behaviors at once via the removeAllBehaviors method.

<span class="co2">// add behaviors to the animator</span>
<span class="br0">[</span>dynamicAnimator addBehavior<span class="sy0">:</span>collisionBehavior<span class="br0">]</span>;
<span class="br0">[</span>dynamicAnimator addBehavior<span class="sy0">:</span>gravityBehavior<span class="br0">]</span>;
 
<span class="co2">// remove a behavior from the animator</span>
<span class="br0">[</span>dynamicAnimator removeBehavior<span class="sy0">:</span>collisionBehavior<span class="br0">]</span>;

The following steps provide a general outline for making UIKit Dynamics work for you:

  1. Determine the types of items you wish to animate then initialize a dynamic animator with the correct initializer. Decide between a UIView, a UICollectionViewLayoutAttributes, or a custom object that conforms to UIDynamicItem.
  2. Identify the objects that you want to animate, making sure they implement the UIDynamicItem protocol. In most cases you won't worry about this since you will be animating UIViews or UICollectionViews.
  3. Initialize a dynamic behavior and specify its dynamic items. Configure the behavior as necessary to define points, boundaries, modes, etc.
  4. Add one or more of your behaviors to a dynamic animator.

In closing, there are a few things you should keep in mind. First, while it is possible to create simple games with UIKit Dynamics, it is recommended that you instead use the SpriteKit framework. UIKit Dynamics is best used to add visual effects to your application, not as a method to manage a large number of simultaneous animations. Second, the most effective animations in non-gaming applications rely on subtlety and seamless integration within your user interface. Try to employ animations that begin and end based on a user action, such as a gesture. Because UIKit Dynamics makes it so easy to animate objects, you might be tempted to do so when it isn't required. Don't force the inclusion of a dynamic animation if it does not add to your user experience. Finally, if your application does require simultaneous animations, CPU utilization may become an issue. According to Apple, collisions are the most CPU-intensive dynamic animation, which makes sense if you consider all the calculations required to determine how colliding objects should react to each other. The sample application includes functionality that will allow you to create a large number of views, add some angular velocity (rotation), and then make them collide with each other. By adjusting the number of views, it is easy to guage how dynamic animations can affect CPU utilization.

I hope you find this post helpful. Happy animating!