UIView animation
cancel animation
iOS development
Swift programming
iOS animations

Cancel a UIView animation?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Canceling a UIView animation is one of those UIKit tasks that sounds simpler than it is. The answer depends on which animation API you used. Classic block-based UIView.animate calls are not truly “cancelable” in the same way as a network request, while UIViewPropertyAnimator gives you much finer control over stopping, pausing, and reversing animation work.

What Happens in a Classic UIView.animate

When you animate a property with UIView.animate, UIKit updates the model layer to the final value right away and lets Core Animation animate the presentation layer over time.

swift
1UIView.animate(withDuration: 1.5) {
2    boxView.alpha = 0.2
3    boxView.center.x = 280
4}

That detail explains why cancellation feels awkward. If you remove the animation from the layer, the view usually snaps to its model-layer value, which is often the final destination, not the current visible position.

So with classic block animations, the real choices are usually:

  • remove the animation and accept the snap
  • capture the current presentation state before removal
  • start a new animation from the current state

Fast Stop by Removing Layer Animations

If you just need to stop the visible motion immediately, remove the layer animation:

swift
boxView.layer.removeAllAnimations()

This is the blunt instrument version. It works, but it can be visually jarring because the model layer may already hold the final value.

If the animated property was center, alpha, or transform, the view may jump when the animation is removed. That is not a bug in removeAllAnimations(). It is how the model and presentation layers interact.

Freeze the Current Visual Position

If you want the view to stay where it appears on screen when you stop the animation, read the presentation layer first and copy that state back to the view.

swift
1if let presentation = boxView.layer.presentation() {
2    boxView.center = presentation.position
3    boxView.layer.removeAllAnimations()
4}

That approach works well for position-based animations. For transforms or opacity, capture the matching presentation values and assign them back to the view before removing animations.

A slightly more complete example:

swift
1func stopAtCurrentPosition(_ view: UIView) {
2    guard let presentation = view.layer.presentation() else {
3        view.layer.removeAllAnimations()
4        return
5    }
6
7    CATransaction.begin()
8    CATransaction.setDisableActions(true)
9    view.center = presentation.position
10    view.layer.removeAllAnimations()
11    CATransaction.commit()
12}

Disabling actions prevents the corrective assignment itself from becoming another implicit animation.

Starting a New Animation Cleanly

Sometimes you do not want to cancel so much as redirect. In that case, beginFromCurrentState is often the best choice.

swift
1UIView.animate(
2    withDuration: 0.4,
3    delay: 0,
4    options: [.beginFromCurrentState, .curveEaseOut],
5    animations: {
6        self.boxView.center.x = 120
7    }
8)

This tells UIKit to begin the new animation from the view’s current presentation state rather than from the old model-layer start value. It is a good fit for interactive interfaces where a swipe, drag, or repeated tap changes the destination mid-animation.

Use UIViewPropertyAnimator for Real Control

If you know in advance that the animation may need to be stopped or paused, use UIViewPropertyAnimator instead of classic block animations.

swift
1import UIKit
2
3let animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeInOut) {
4    boxView.alpha = 0.2
5    boxView.transform = CGAffineTransform(scaleX: 1.4, y: 1.4)
6}
7
8animator.startAnimation()

Now you can interrupt it explicitly:

swift
animator.stopAnimation(true)

Or pause and inspect progress:

swift
animator.pauseAnimation()
print(animator.fractionComplete)

This API is better when the UI is interactive because the animation object has its own lifecycle instead of being a fire-and-forget closure.

Choosing the Right Strategy

Use these rules:

  • if you only need to stop visual movement right now, remove layer animations
  • if you need the view to stay where it currently appears, copy presentation values first
  • if you need interruption as a designed feature, use UIViewPropertyAnimator
  • if you only need to redirect motion, animate again with .beginFromCurrentState

That framing is more useful than asking whether UIView animations are “cancelable” in the abstract.

Common Pitfalls

The biggest pitfall is calling removeAllAnimations() and being surprised when the view jumps. The model layer may already hold the destination value.

Another issue is trying to build highly interactive motion on top of UIView.animate when UIViewPropertyAnimator is a better tool.

Developers also sometimes forget that presentation() can be nil if no animation is active, so stop logic needs a fallback path.

Finally, copying presentation-layer state without disabling implicit actions can create a second unwanted animation.

Summary

  • Classic UIView.animate animations are not truly cancelable objects.
  • 'layer.removeAllAnimations() stops visible animation but may cause a snap.'
  • To freeze the current look, copy state from the presentation layer before removing animations.
  • '.beginFromCurrentState is useful when you want to redirect an animation smoothly.'
  • 'UIViewPropertyAnimator is the best API when interruption and cancellation are first-class requirements.'

Course illustration
Course illustration

All Rights Reserved.