由于暂停动画和NSInternalInconsistencyException

时间:2017-07-22 16:01:19

标签: ios swift animation uikit

通过拉起并向下滑动,我可以在屏幕上和屏幕上显示UIView。我使用这段代码来做到这一点:

private var _animator: AnyObject?
@available(iOS 10.0, *)
var animator: UIViewPropertyAnimator? {
    get {
        return _animator as? UIViewPropertyAnimator
    }
    set {
        _animator = newValue
    }
}
var haveTheySwiped = false
var haveTheyNotSwiped = true

@available(iOS 10.0, *)
func handlePan(recognizer: UIPanGestureRecognizer) {
    let vel = recognizer.velocity(in: self)
        switch recognizer.state {
        case .began:
            if vel.y < 0 && !haveTheySwiped {
                animator = UIViewPropertyAnimator(duration: 1, curve: .easeOut, animations: {
                    self.backgroundImage.frame = self.backgroundImage.frame.offsetBy(dx: 0, dy: -603)
                })
                haveTheySwiped = true
                isScanVisible = true
            } else if vel.y > 0 && haveTheySwiped {
                animator = UIViewPropertyAnimator(duration: 1, curve: .easeOut, animations: {
                    self.backgroundImage.frame = self.backgroundImage.frame.offsetBy(dx: 0, dy: 603)
                })
                haveTheySwiped = false
                isScanVisible = false
            }
            animator?.pauseAnimation()
            print(backgroundImage.frame.origin)
        case .changed:
            let translation = recognizer.translation(in: backgroundImage)
            if vel.y < 0 {
                animator?.fractionComplete = translation.y / -603
            } else if vel.y > 0 && haveTheySwiped == true {
                animator?.fractionComplete = translation.y / 603
            }
        case .ended:
            animator?.continueAnimation(withTimingParameters: nil, durationFactor: 0)
        case .possible: break
        default: break
        }
}

但是,最近我遇到了一个错误。当我试图拉起时,UIView没有出现,然后当我抬起手指时,应用程序因此错误而崩溃:

  

***因未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'发布时出错   暂停或停止的属性动画师。物业动画师必须要么   完成动画或明确停止并完成它们之前   被释放。'

有没有人碰到过这个?愿意帮助找出导致这种情况发生的原因。任何帮助都会非常感激。非常感谢提前!

干杯, THOE

7 个答案:

答案 0 :(得分:2)

万一有人在2019年或更晚的时候仍然发生此崩溃,我的动画师也遇到了类似的问题,我只需要运行25%的分数就可以完成(在collectionView单元上创建微妙的模糊效果)。

当单元格被取消初始化或从navController中弹出VC时,将发生崩溃。

在我的单元的UI设置中,我具有以下实现方式

之前:导致崩溃

 animator?.fractionComplete = 0.25

之后:不再崩溃

 animator?.fractionComplete = 0.25
 animator?.stopAnimation(true) 
 animator?.finishAnimation(at: .current)

这帮了我大忙。

答案 1 :(得分:1)

这里的错误通常是由于系统在回到.inactive状态之前试图清除动画师的事实。

我看不到你的所有代码。

但一般来说,这样的事情会崩溃

  private func animating(){
    let animation = UIViewPropertyAnimator(duration: 3, curve: .linear) {
        [weak self] in
        self?.view.backgroundColor = .red
    }

    animation.startAnimation()
    animation.pauseAnimation()
}

当动画功能完成后,系统将尝试清除您创建的UIViewPropertyAnimator(该属性不在定义范围之外),但动画暂停,这意味着它仍然处于.active状态(同样适用于animation.stopAnimation(),就像在这种情况下它是.stop状态),就像我上面提到的那样,任何时候当你尝试在重新开启之前清除动画师时。处于非活动状态,系统将抛出错误。

所以,在这种情况下的解决方案,如果你想中途停止或停止动画,你需要找到一种方法来保留动画师。

例如,您可以在viewController中创建一个属性,如

var animation : UIViewPropertyAnimator!

但是你需要确保动画师在允许系统清除它之前回到.inactive状态,否则崩溃将再次发生。

答案 2 :(得分:0)

实现stopAnimation(Bool)然后finishAnimation(at:UIViewAnimatingPosition)应该解决问题。

  

该类采用UIViewAnimating和UIViewImplicitlyAnimating   协议,定义启动,停止和启动的方法   修改动画。有关方法的更多信息   那些协议,请参阅UIViewAnimating和UIViewImplicitlyAnimating   

https://developer.apple.com/documentation/uikit/uiviewanimating

  

func stopAnimation(Bool)   停止当前的动画   位置。需要。

     

func finishAnimation(at:UIViewAnimatingPosition)   完成动画并将动画制作者返回到不活动状态   州。必需的。

答案 3 :(得分:0)

我有一个类似的错误,它是间歇性发生的。诸如animator.startAnimation(afterDelay: 1)之类的文件崩溃了。进一步调用stopAnimationfinishAnimation可能仍然会崩溃,因此检查动画制作器的状态可确保在不应该调用动画器时不会调用它。

if animator.state == .inactive {
animator.startAnimation(afterDelay: 1) 
}

根据您的实现,您可以进行不同的处理。但是,检查动画器的状态将确保不会导致崩溃的命令被调用。

对于OP来说可能并不是完全有帮助,但是对于需要动画师处于特定状态的类似错误,此答案首先出现。

答案 4 :(得分:0)

Swift 5.x:

animator?.stopAnimation(true)
if let animator = animator, animator.state != .inactive {
    animator.finishAnimation(at: .current)
}

我们所解决的问题。

答案 5 :(得分:0)

动画师的状态应该是.inactive。 要实现这一点,您只需要在适当的时候调用 animator.stopAnimation(true)

我在 ViewController 中使用它并在离开屏幕时崩溃。我需要在 super.viewDidDisappear(animated) 之前调用它。

答案 6 :(得分:0)

我遇到了同样的问题,结合这个问题的知识帮助我解决了这个问题:

override func viewWillDisappear(_ animated: Bool) {
    
    articleHeader?.animator.stopAnimation(true)
    
    if let animator = articleHeader?.animator, animator.state != .inactive {
        animator.finishAnimation(at: .current)
    }
}

@programmingbeginner 和他的输入“但是你需要确保动画师在你允许系统清除它之前回到 .inactive 状态,否则就会发生崩溃再次。”帮助我理解我们需要在 UIViewController 从导航堆栈中弹出之前返回到 .inactive 。执行此操作的地方是 viewWillDisappear()。

您还需要在 UICollectionView 中保留对动画师的引用(我的动画师在 ArticleHeader 视图中)。

@atereshkov:我正在使用他的代码来检查动画师是否仍然处于活动状态。

要在 UICollectionViewController 中保持对 ArticleHeader 动画器的引用:

var articleHeader: ArticleHeader?

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    // assign the header here
    articleHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: ArticleHeader.reuseIdentifier, for: indexPath) as? ArticleHeader
    
    // do any header configuration here
   
    return articleHeader!
}

希望它在未来对某人有所帮助。