4

我正在使用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)")
        }
    }
}

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

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

在输出上打印时:

>> before stopping: true
>> after stopping: true

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

这怎么可能?

4

1 回答 1

5

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

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

runningAnimator!.addCompletion({ [unowned self] (_) in
    self.runningAnimator = nil
})

现在的问题是didSet该完成块调用了该部分。runningAnimator已经完成了,我猜因为代码didSet是在完成块期间发生的,所以oldValue.stopAnimation(false)直到完成块还没有完成,才能真正停止动画师。

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

于 2018-01-18T13:18:50.570 回答