NSInternalInconsistencyException:Animator已停止的偶发崩溃原因咨询
UIViewPropertyAnimator 已停止异常分析与解答
异常信息
libc++abi: terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Animator <UIViewPropertyAnimator(0x600003f24200) [stopped] interruptible> is already stopped!'
触发代码
// other code up here that modifies offsetAnimator ... // stop any current running animations on offset if let offsetAnimator = offsetAnimator { offsetAnimator.stopAnimation(false) // 异常触发点 offsetAnimator.finishAnimation(at: .end) }
错误原因
UIViewPropertyAnimator的stopAnimation(_:)方法有严格的状态限制:仅能在动画处于.active状态(运行中或已暂停)时调用。如果动画已经处于.stopped或.inactive状态(动画已完成、已被强制停止或未启动),调用该方法会直接抛出NSInternalInconsistencyException异常。
为何异常仅偶发?
异常的偶发性源于动画状态的不确定性:
- 代码中的
offsetAnimator可能在进入if let判断块之后、调用stopAnimation之前,已经因其他逻辑切换到非.active状态。比如动画刚好在这个间隙自然完成,或者其他异步回调提前调用了stopAnimation/finishAnimation改变了状态。 - 多线程干扰:如果有其他线程触发了动画状态变更(尽管UIKit操作应在主线程,但某些回调可能在非主线程间接修改状态),也会导致状态检查和实际调用之间出现不一致。
为什么连续调用两次stopAnimation不总是报错?
第一次调用stopAnimation(false)时,若动画处于.active状态,调用后动画会进入暂停的.active状态(而非直接变为.stopped),此时第二次调用stopAnimation(false)仍处于合法状态范围内,不会触发异常。
只有当第一次调用后,动画状态因系统内部延迟、额外回调等原因提前切换到.stopped/.inactive,第二次调用才会报错——这种场景出现概率较低,因此你观察到的是偶发错误。
解决方案
在调用stopAnimation前,先检查动画状态是否为.active,避免对已停止/完成的动画执行非法操作:
if let offsetAnimator = offsetAnimator, offsetAnimator.state == .active { offsetAnimator.stopAnimation(false) offsetAnimator.finishAnimation(at: .end) }
同时建议规范offsetAnimator的生命周期管理:动画完成或停止后,及时将其置为nil,避免后续代码操作已失效的动画实例。
内容的提问来源于stack exchange,提问作者AlanSTACK
相关产品推荐
相关产品推荐

