UIViewPropertyAnimator 未在 stopAnimation 上停止

Mil*_*sáľ 6 animation ios swift uiviewpropertyanimator

我用来UIViewPropertyAnimator动画化与我的视图的交互(在卡片之间滑动)。一切都工作正常,直到最近我在生产中遇到以下崩溃:

致命异常:NSInternalInconsistencyException

释放已暂停或已停止的属性动画器是错误的。属性动画师必须完成动画制作或明确停止并完成才能释放。

由于 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)")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,现在我的应用程序开始因以下错误而崩溃:

'NSInternalInconsistencyException',原因:'finishAnimationAtPosition:只能在停止的动画师上调用!'

在输出上打印时:

>> before stopping: true
>> after stopping: true
Run Code Online (Sandbox Code Playgroud)

很明显,oldValue即使在调用后动画师仍在运行oldValue.stopAnimation(false)

这怎么可能?

Mil*_*sáľ 6

现在经过一个多小时的查找、调试、分析,我终于找到了发生这种情况的原因。我分享这个是为了希望避免其他人落入这个陷阱。

创建 后,我添加了一个完成块,当动画师完成时runningAnimator该完成块应该设置为 nil:runningAnimator

runningAnimator!.addCompletion({ [unowned self] (_) in
    self.runningAnimator = nil
})
Run Code Online (Sandbox Code Playgroud)

现在的问题是该didSet部分被这个完成块调用。已经完成了runningAnimator,我猜由于代码didSet是在完成块期间发生的,因此oldValue.stopAnimation(false)在完成块尚未完成之前无法真正停止动画师。

只是为了记录,虽然这看起来可能存在无限递归,但这不应该发生,因为在已经完成的动画师上调用stopAnimationandfinishAnimation不会再次调用完成块。