I animate a UIView on and off the screen by pulling up and swiping down. I use this code to do that:
private var _animator: AnyObject?
@available(iOS 10.0, *)
var animator: UIViewPropertyAnimator? {
get {
return _animator as? UIViewPropertyAnimator
}
set {
_animator = newValue
}
}
var haveTheySwiped = false
var haveTheyNotSwiped = true
@available(iOS 10.0, *)
func handlePan(recognizer: UIPanGestureRecognizer) {
let vel = recognizer.velocity(in: self)
switch recognizer.state {
case .began:
if vel.y < 0 && !haveTheySwiped {
animator = UIViewPropertyAnimator(duration: 1, curve: .easeOut, animations: {
self.backgroundImage.frame = self.backgroundImage.frame.offsetBy(dx: 0, dy: -603)
})
haveTheySwiped = true
isScanVisible = true
} else if vel.y > 0 && haveTheySwiped {
animator = UIViewPropertyAnimator(duration: 1, curve: .easeOut, animations: {
self.backgroundImage.frame = self.backgroundImage.frame.offsetBy(dx: 0, dy: 603)
})
haveTheySwiped = false
isScanVisible = false
}
animator?.pauseAnimation()
print(backgroundImage.frame.origin)
case .changed:
let translation = recognizer.translation(in: backgroundImage)
if vel.y < 0 {
animator?.fractionComplete = translation.y / -603
} else if vel.y > 0 && haveTheySwiped == true {
animator?.fractionComplete = translation.y / 603
}
case .ended:
animator?.continueAnimation(withTimingParameters: nil, durationFactor: 0)
case .possible: break
default: break
}
}
But, recently I have come across a bug. When I try to pull up, the UIView does not appear and then when I lift my finger up, the app crashes with this error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'It is an error to release a paused or stopped property animator. Property animators must either finish animating or be explicitly stopped and finished before they can be released.'
Has anyone come across this? Would love some help figuring out what is causing this to happen. Any help would be immensely appreciated. Thanks so much in advance!
Cheers, Thoe
In case somebody still gets this crash in 2019 or later, I had a similar issue with an animator I only needed to run for 25% of its fraction complete (to create a subtle blur on a collectionView cell).
The crash would occur when the cell would be deinit or when the VC would be popped from the navController.
Inside the UI setup of my cell, I had the below implementation
Before: leading to crash
animator?.fractionComplete = 0.25
After: no more crash
animator?.fractionComplete = 0.25
animator?.stopAnimation(true)
animator?.finishAnimation(at: .current)
This did the trick for me.
The error here is generally due to the fact that the System is trying to clear the animator before it is back to .inactive state.
I don see all your codes.
But generally, something like this will crash
private func animating(){
let animation = UIViewPropertyAnimator(duration: 3, curve: .linear) {
[weak self] in
self?.view.backgroundColor = .red
}
animation.startAnimation()
animation.pauseAnimation()
}
When the animating function is completed, the system will try to clear the UIViewPropertyAnimator you have created (the property does not live outside of the define scope), but the animation is paused, which means it is still at the .active state (the same goes to animation.stopAnimation(), just that in this case it is .stop state), and like I mention above, anytime when you try to clear the animator before it is back on .inactive state, the system will throw an error.
So, the solution in this case, if you wish to pause or stop animation halfway, you need to find a way to retain the animator.
For example, you can create a property in the viewController like
var animation : UIViewPropertyAnimator!
But you need to make sure that the animator goes back to .inactive state before you allow the system to clear it, or else the crash will just happen again.
Implementing stopAnimation(Bool) then finishAnimation(at: UIViewAnimatingPosition) should clear up the problem.
This class adopts the UIViewAnimating and UIViewImplicitlyAnimating protocols, which define the methods for starting, stopping, and modifying your animations. For more information about the methods of those protocols, see UIViewAnimating and UIViewImplicitlyAnimating .
https://developer.apple.com/documentation/uikit/uiviewanimating
func stopAnimation(Bool) Stops the animations at their current positions. Required.
func finishAnimation(at: UIViewAnimatingPosition) Finishes the animations and returns the animator to the inactive state. Required.
Swift 5.x:
animator?.stopAnimation(true)
if let animator = animator, animator.state != .inactive {
animator.finishAnimation(at: .current)
}
Fixed problem in our case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With