A Beginner’s Guide to Core Animation in iOS

Guide to Core Animation

Core Animation might seem intimidating for new iOS developers, but it’s essential to understand how animations work under the hood. While UIKit (and SwiftUI) provide high-level APIs for animations, Core Animation (CA) is the underlying system responsible for the motion you see.

Understanding Core Animation

Core Animation manages the visual content of your app using CALayer objects. Every UIView has an associated CALayer that you can manipulate directly if you need more fine-grained control than UIKit’s higher-level animation APIs. This is helpful when you need effects that aren’t possible through property-based animators or standard view transitions.

Under the hood, Core Animation uses two models:

  • The model layer: Reflects the “real” values of the view’s properties (position, size, corner radius, etc.).
  • The presentation layer: Reflects the current onscreen values during an active animation. When the animation completes, you usually update the model layer to match the final animated state.

1. Moving a View

Below is a basic Swift example showing how to move the image from one position to another using Core Animation:

class ViewController: UIViewController {
    
    let duck = UIImageView(image: UIImage(named: "duck"))
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor(named: "orange")
        
        view.addSubview(duck)
        animateLeftToRight()
    }
    
    private func animateLeftToRight() {
        let animation = CABasicAnimation()
        animation.keyPath = "position.x"
        animation.fromValue = 20 + 140/2
        animation.toValue = 300
        animation.duration = 1
        
        duck.layer.add(animation, forKey: "move")
        
        // defines the final position so it doesn't reset
        duck.layer.position = CGPoint(x: 300, y: 100 + 100/2)
    }
}

You can get the source code of this project here

When you remove the line that sets redView.layer.position.x = 300, the square will slide then “snap back” to its original position because the model layer wasn’t updated with the animation’s final value.

2. Scaling a View

Need to grow or shrink a view? You can animate the scale using the "transform.scale" keyPath:

private func animateScale() {
    let animation = CABasicAnimation()
    animation.keyPath = "transform.scale"
    animation.fromValue = 1
    animation.toValue = 2
    animation.duration = 2
    
    duck.layer.add(animation, forKey: "scale")
    
    // defines the final scale
    duck.layer.transform = CATransform3DMakeScale(2, 2, 1)
}

3. Rotation

Rotating a view about its Z-axis is similar, except you use "transform.rotation.z":

private func animateRotation() {
    let animation = CABasicAnimation()
    animation.keyPath = "transform.rotation.z" // z-axis
    animation.fromValue = 0
    animation.toValue = CGFloat.pi / 4 //45 degress in radians
    animation.duration = 2
    
    duck.layer.add(animation, forKey: "rotate")
    duck.layer.transform = CATransform3DMakeRotation(CGFloat.pi / 2, 0, 0, 1)
}

Here, "transform.rotation.z" indicates rotation about the Z-axis (the axis “coming out of the screen”).

4. Keyframe Animations (Shake Effect)

Keyframe animations let you define multiple points in time, making it easy to create effects like “shaking” a login form when the user enters invalid credentials:

private func animateShakeTextField() {
      let animation = CAKeyframeAnimation()
      animation.keyPath = "position.x"
      animation.values = [0, 10, -10, 10, 0]
      animation.keyTimes = [0, 0.16, 0.5, 0.83, 1]
      animation.duration = 0.4
      
      animation.isAdditive = true
      duck.layer.add(animation, forKey: "shake")
}

You can apply this same approach to any view—just change "position.x" to "position.y" or another property as needed.

Tips for Using Core Animation

  1. Update the Model Layer
    Always remember to set the final position or transform on the view’s model layer if you want its new state to persist after the animation finishes.
  2. Anchor Point Gotchas
    The default anchor point is the view’s center. If you change your view’s anchor point, your animations might shift unpredictably if you don’t adjust positions accordingly.
  3. Coordinate System
    Core Animation uses a coordinate system that starts at the top-left corner, increasing down and to the right. For position-based animations, ensure you calculate the correct center points (especially if you set frames or anchor points manually).
  4. Combine with UIKit
    You can mix these animations with standard UIKit property animators. This is sometimes easier for simpler transitions, but dropping down to Core Animation’s layer-based approach gives you maximum power.
  5. Experiment in Small Steps
    Because it’s easy to get lost in the details of the model/presentation layer, test small animations first. Even drawing a shape or path to see if it lines up with what you expect can make debugging much easier.

Conclusion

Core Animation unlocks a wealth of possibilities beyond UIKit or SwiftUI’s higher-level animations. By understanding how CALayer, keyPaths, and the model/presentation layers work, you can combine transforms, positions, and keyframe animations to produce delightful user experiences.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *