UIViewPropertyAnimator不会在stopAnimation上停止

时间:2018-01-18 13:18:51

标签: ios swift animation 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)")
        }
    }
}

然而,现在我的应用程序开始崩溃,出现此错误:

  

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

在输出上打印时:

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

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

这怎么可能?

1 个答案:

答案 0 :(得分:2)

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

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

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

现在的问题是didSet部分被这个完成块调用了。 runningAnimator已经完成,我想因为didSet代码在完成块期间发生,oldValue.stopAnimation(false)无法真正停止动画师,直到完成块还没有完成。

仅仅为了记录,虽然看起来这里有无限递归,但这不应该发生,因为在已经完成的动画师上调用stopAnimationfinishAnimation不会再次调用完成块。