UIViewPropertyAnimator 不会停止在 stopAnimation 上
UIViewPropertyAnimator not stopping on stopAnimation
我正在使用 UIViewPropertyAnimator
来动画化与我的视图的交互(在卡片之间滑动)。一切正常,直到最近我在生产中遇到以下崩溃:
Fatal Exception: NSInternalInconsistencyException
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.
由于 Crashlytics 并没有真正提供更多上下文,或者我能做的就是确保我的所有动画师总是在 viewController
发布之前完成。
在我的一次尝试中,我试图确保当我创建一个新的动画师时,旧的动画师会停止并完成:
fileprivate var runningAnimator: UIViewPropertyAnimator? {
didSet {
if let oldValue = oldValue {
print(">> before stopping: \(oldValue.isRunning)")
oldValue.stopAnimation(false)
print(">> after stopping: \(oldValue.isRunning)")
oldValue.finishAnimation(at: .end)
print(">> after finishing: \(oldValue.isRunning)")
}
}
}
但是,现在我的应用开始崩溃并出现以下错误:
'NSInternalInconsistencyException', reason: 'finishAnimationAtPosition: should only be called on a stopped animator!'
在打印输出时:
>> before stopping: true
>> after stopping: true
很明显 oldValue
动画师即使在调用 oldValue.stopAnimation(false)
之后仍然是 运行。
这怎么可能?
现在经过一个多小时的查找、调试、分析,终于找到了发生这种情况的原因。我分享这个是为了希望能避免其他人落入这个陷阱。
在创建 runningAnimator
之后,我添加了一个完成块,当动画师完成时应该将 runningAnimator
设置为 nil:
runningAnimator!.addCompletion({ [unowned self] (_) in
self.runningAnimator = nil
})
现在的问题是 didSet
部分被这个完成块调用了。 runningAnimator
已经完成,我猜因为 didSet
代码是在完成块期间发生的,所以 oldValue.stopAnimation(false)
在完成块还没有完成之前无法真正停止动画师。
仅作记录,虽然这看起来似乎有无限递归,但这不应该发生,因为在已经完成的动画器上调用 stopAnimation
和 finishAnimation
不会调用完成块再次.
我正在使用 UIViewPropertyAnimator
来动画化与我的视图的交互(在卡片之间滑动)。一切正常,直到最近我在生产中遇到以下崩溃:
Fatal Exception: NSInternalInconsistencyException
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.
由于 Crashlytics 并没有真正提供更多上下文,或者我能做的就是确保我的所有动画师总是在 viewController
发布之前完成。
在我的一次尝试中,我试图确保当我创建一个新的动画师时,旧的动画师会停止并完成:
fileprivate var runningAnimator: UIViewPropertyAnimator? {
didSet {
if let oldValue = oldValue {
print(">> before stopping: \(oldValue.isRunning)")
oldValue.stopAnimation(false)
print(">> after stopping: \(oldValue.isRunning)")
oldValue.finishAnimation(at: .end)
print(">> after finishing: \(oldValue.isRunning)")
}
}
}
但是,现在我的应用开始崩溃并出现以下错误:
'NSInternalInconsistencyException', reason: 'finishAnimationAtPosition: should only be called on a stopped animator!'
在打印输出时:
>> before stopping: true
>> after stopping: true
很明显 oldValue
动画师即使在调用 oldValue.stopAnimation(false)
之后仍然是 运行。
这怎么可能?
现在经过一个多小时的查找、调试、分析,终于找到了发生这种情况的原因。我分享这个是为了希望能避免其他人落入这个陷阱。
在创建 runningAnimator
之后,我添加了一个完成块,当动画师完成时应该将 runningAnimator
设置为 nil:
runningAnimator!.addCompletion({ [unowned self] (_) in
self.runningAnimator = nil
})
现在的问题是 didSet
部分被这个完成块调用了。 runningAnimator
已经完成,我猜因为 didSet
代码是在完成块期间发生的,所以 oldValue.stopAnimation(false)
在完成块还没有完成之前无法真正停止动画师。
仅作记录,虽然这看起来似乎有无限递归,但这不应该发生,因为在已经完成的动画器上调用 stopAnimation
和 finishAnimation
不会调用完成块再次.