UIViewPropertyAnimator completion called when paused

Viewed 3330

I haven’t used UIViewPropertyAnimator very much (still an old fashioned blocks guy) and I’m seeing some behavior that I can’t explain and that the docs don’t really provide any insight on.

Why does an animator’s completion block get called with a finalPosition of .end even when the animator is paused immediately after it’s started?

let view = UIView()
let animator = UIViewPropertyAnimator(duration: 4, curve: .linear, animations: {
    view.alpha = 0
})

animator.addCompletion { position in
    print("done")
    switch position {
    case .start: print("start")
    case .current: print("current")
    case .end: print("end")
    }
}

animator.startAnimation()
print("starting")
animator.pauseAnimation()
print("pausing")

Output:

starting
pausing
done
end
2 Answers

The problem, as @matt alluded to, is that your view isn't in a visible UIWindow, so the animations complete immediately. You get the same output if you comment out the animator.pauseAnimation() statement.

You can fix this if you're using a playground by making view the liveView of the playground page:

import PlaygroundSupport
import UIKit

let view = UIView()
PlaygroundPage.current.liveView = view

// etc.

If you read the documentation of addCompletion from Apple's developer site, one of the parameter is the finalPosition. And you can use the value to determine whether the animation stopped at the beginning, end, or somewhere in the middle. And calling pauseAnimation will trigger that completion block with a somewhere in the middle position.

Parameters completion A block to execute when the animations finish. This block has no return value and takes the following parameter:

finalPosition The ending position of the animations. Use this value to determine whether the animations stopped at the beginning, end, or somewhere in the middle.

Related