UIViewPropertyAnimator completion called when paused
Asked Answered
S

2

7

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
Simonsimona answered 16/1, 2019 at 23:41 Comment(2)
Session 216 from WWDC 216 and Session 230 from WWDC 2017 are well worth two hours of your time if you're starting to play with property animators. Really good introductions.Comyns
Thanks for the links — I've seen both of these in the past and will give them another go.Simonsimona
D
3

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.
Dew answered 17/1, 2019 at 4:42 Comment(0)
R
0

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.

Railhead answered 17/1, 2019 at 0:1 Comment(2)
That's what I figured, but why would calling pauseAnimation() immediately after startAnimation() call the completion with a finalPosition of .end?Simonsimona
I assuming startAnimation is an async function, so If you are calling the pauseAnimation immediately after that then that would trigger the completion right away. If pauseAnimation will be called via a user-event trigger then you will get a different result I suppose.Railhead

© 2022 - 2024 — McMap. All rights reserved.