I have this code in a Factory class to return UIViewPropertyAnimators to be used where and when:
class AnimatorFactory {
@discardableResult
static func spinSpindle(spindle: UIView) -> UIViewPropertyAnimator {
let spinSpindleAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear)
spinSpindleAnimator.addAnimations {
spindle.transform = CGAffineTransform(rotationAngle: .pi)
}
spinSpindleAnimator.addCompletion{ position in
print("spinSpindle.complete: \(position.rawValue)")
spindle.transform = .identity
self.spinSpindle(spindle: spindle)
}
spinSpindleAnimator.startAnimation()
return spinSpindleAnimator
}
...
The code creates a UIViewPropertyAnimator
that allows for a perpetually animating view (one that keeps on spinning and spinning). It does this by calling itself again in the completion block. The problem I have now is that I am unable to stop the animation using UIViewPropertyAnimator.stopAnimation(true)
.
The true
in stopAnimation(_ withoutFinishing:)
value is meant to ensure that the animation is returned to the UIViewAnimatingState.inactive
state without having to perform any cleanup with finishAnimation(at finalPosition:)
.
When I call stopAnimation(true)
the animation does not stop. It is called like this:
print("\(spindleAnimator.description)")
spindleAnimator.stopAnimation(true)
print("\(spindleAnimator.description)")
The above code is triggered by the user tapping on the animating view and outputs this:
<UIViewPropertyAnimator(0x600001c1c100) [inactive] interruptible>
<UIViewPropertyAnimator(0x600001c1c900) [inactive] interruptible>
To me this suggests that the spindleAnimator
refers to a different UIViewPropertyAnimator
due to the "recursive" call in the AnimatorFactory.spinSpindle(spindle:)
static method. I might be mistaken.
Essentially I'm looking for help in order to create a truly interactive and repeating animation. So far I've been having incredible trouble with it, but I won't complain as I've learned a lot. However, I need some help tying it all together by finding a working stopAnimation(withoutFinishing:)
call.
Thanks!
EDIT:
Another interesting fact is that I am able to stop the animation if I click the spindle before it completes its first revolution (in other words, before the completion block is executed). This leads me to believe that the "recursive" call to spinSpindle(spindle:)
creates another UIViewPropertyAnimator for which I have no handle to call stopAnimation(withoutFinishing:)
. Although, I don't think I see how this is the case...
I tested this theory by printing spinSpindleAnimator.description
each time the call to spinSpindle(spindle:)
is made:
class AnimatorFactory {
@discardableResult
static func spinSpindle(spindle: UIView) -> UIViewPropertyAnimator {
let spinSpindleAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear)
spinSpindleAnimator.addAnimations {
spindle.transform = CGAffineTransform(rotationAngle: .pi)
}
spinSpindleAnimator.addCompletion{ position in
print("(\(spinSpindleAnimator.description)) spinSpindle.complete: \(position.rawValue)")
spindle.transform = .identity
self.spinSpindle(spindle: spindle)
}
spinSpindleAnimator.startAnimation()
return spinSpindleAnimator
}
and it gives
(<UIViewPropertyAnimator(0x600001b20300) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b28b00) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38600) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b31000) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38300) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38600) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b38700) [unknown] running interruptible>) spinSpindle.complete: 0
(<UIViewPropertyAnimator(0x600001b20600) [unknown] running interruptible>) spinSpindle.complete: 0
...
confirming my suspicions.