Chain Animations in Swift

One animation after another

Image for post
Image for post
Photo by JJ Ying on Unsplash

Anyone who has use animations in Swift will have become (possibly unwillingly) familar with an animation pyramid. Look further for both an example of this, and how you can avoid being another pyramid victim.

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

Terminology

UIView: An object that manages the content for a rectangular area on the screen

The challenge

You might well have dabbled with animations in Swift. Good for you! They are fun, and we can see a problem developing if we start to chain animations using animateWithDuration:animations:completion:

Image for post
Image for post
Click for Gist

it’s a mess! This could be a pyramid of DOOM.

This isn’t a fully working example, so this article will take us through a simple animation and how it might be coded using the best that UIKit has to offer us.

Are you ready? Let us get started!

The example

Let’s see an animation of a rectangle coming onto the screen, rotating and zooming and then then making a swift exit off the side of the screen. Something a little like the following:

Image for post
Image for post

This is possible by using the following code that I whacked into func viewDidAppear(_ animated: Bool):

Image for post
Image for post
Click for Gist

Which, as you can see has three calls to class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil) which means we have a great solution that:

  • isn’t easy to read
  • is difficult to maintain
  • that I’m not really sure what is going to happen when reading the code

I’ve made a Gist with the full view controller class to help you

There must be a better way.

Step in the animateKeyframes

The method creates an animation block to be used in keyframe animations. The class signature is slightly intimidating, an man there are a large number of UIView.KeyframeAnimationOptions within that.

animateKeyframes(withDuration:delay:options:animations:completion:)

Let us look at the solution before we dive in:

Image for post
Image for post
Click for Gist

This works functionally exactly the same as the animate method shown at the top of this article.

It does so with the (initial) parameters for animatKeyFrames:

withDuration: The duration for the animation

delay: The wait time before the animation starts

options: A set of options that can be picked. Choice picks are .autoreverse (which has to be used with .repeat) and .allowUserInteraction (Apple have a full list of these)

animations: The animations using Keyframe(withRelativeStartTime:relativeDuration:animations:). More on that in a minute.

completion: Not shown here, but an optional completion block

Remember when I said we’d come back to Keyframe(withRelativeStartTime:relativeDuration:animations:)? This is that time.

addKeyframe(withRelativeStartTime:relativeDuration:animations:)

has the following parameters:

frameStartTime: A relative value between 0 and 1. In the example above I’ve equally spaced the times apart by using 0, 0.33 and 0.66 — and the first of those will start immediately.

frameDuration: The relative duration, so in my example I set each key frame to have a duration of 0.25

animations: The block containing the animations; that is in order the appearance, transform and scale followed by the exit.

Did you know

You can overlap the keyframes! There’s nothing wrong with that, and you can certainly make a number of fun effects doing so! Awesome!

So keyframes allow you flexibility, and avoid that rather nasty nested set of blocks. However, you may still have to use UIView.animate. You can’t win them all.

Conclusion:

We’ve all used completion handlers to manage the flow of data within our App. This is usually a great solution, and certainly won’t cause you irretrievable issues in your App. However, the programmers pyramid of doom makes code difficult to maintain and add features to in the future?

The solution — animateKeyframes — will help you create applications that will pass your code reviews and enable you to produce quality code.

Isn’t that what we are all here for?

If you want to get in touch, hit me up on Twitter.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store