Search code examples
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 an instance property using any one of its initializers:

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

    This will allow you to re-add animations to it using addAnimations() which is what we want to do since the animations themselves are nilled at the end of each call to start one. Therefore, before calling startAnimation(), we must always give it animations (usually the same ones each time).

    @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 to start, I think this is cleaner.