iosswiftuiviewanimationuiviewpropertyanimator

Restart UIViewPropertyAnimator when returning to the App


I just built an iOS app with a simple animation. But I am struggling with the UIViewPropertyAnimator. I want to animate a button and this works well until I leave the app (pressing home button) and going back to it. The animation has stopped and won't start again. I tried to stop the animation and start it again after the ViewController didBecomeActive but that doesn't work either.

I start the animation in the viewDidAppear method as follows:

var animator: UIViewPropertyAnimator!

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification,object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeInActive), name: UIApplication.willResignActiveNotification,object: nil)

        //Start Animation
        animator = UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 1, delay: 0, options: [.autoreverse, .repeat], animations: {
            UIView.setAnimationRepeatAutoreverses(true)
            UIView.setAnimationRepeatCount(1000)
            self.scanButton.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
        }, completion: nil)
        animator.startAnimation()
    }

And here the code where I stop and restart the animation:

@objc func applicationDidBecomeActive() {
        print("Active")
        animator.startAnimation()
}

@objc func applicationDidBecomeInActive() {
        print("InActive")
        animator.stopAnimation(true)
        animator.finishAnimation(at: .current)  
}

I hope you guys know how to solve this. Thanks in advance.


Solution

  • What you can do is make animator a scoped property using any one of its initializers, such as the following.

    private var animator = UIViewPropertyAnimator(duration: 1, curve: .linear, animations: nil)
    

    This will allow you to re-add animations using addAnimations(), which is what we must do since the animations themselves are lost after each call. Therefore, before calling startAnimation(), give it animations.

    @objc func applicationDidBecomeActive() {
        print("Active")
        animator.addAnimations {
            // re-add animation
        }
        animator.startAnimation()
    }
    

    You can also add the animations to the initializer itself but since we're adding it before each call, I think this is cleaner.