iosswiftuiviewanimationviewwillappear

UIView Animation and UIButton stop working b/c Home pressed - Swift 4


I have a playButton that performs a "breathing animation". The button works just fine when I press it. The problem occurs if I press the device's Home Button and then re-open the app. Upon re-opening, the playButton does not have the "breathing animation" and it does not work (nothing happens when it is pressed).

@IBOutlet weak var playButton: UIButton!

override func viewWillAppear(_ animated: Bool) {

    UIView.animate(withDuration: 1.0,
                   delay: 0,
                   options: [.autoreverse, .repeat, .allowUserInteraction],
                   animations: {
                    self.playButton.transform = CGAffineTransform(scaleX: 1.175, y: 1.175)
    },
                   completion: nil

    )

 }

I've dealt with this issue in a previous game app where I needed to save and pause the game if the user pressed the Home Button or if there was an interruption (incoming call). So, I am well aware of:

func applicationDidBecomeActive() {}

func applicationWillResignActive() {}

func applicationDidEnterBackground() {}

But, I am not dealing with a gameState, timer, the need to save data, etc. I simply want my button and its animation to work properly when the app re-opens after the Home Button is pressed.

I also tried using override func viewDidLayoutSubviews() {} instead of viewWillAppear. But that did not work.


Solution

  • First of all, if you have a multiple animations within the same ViewController (VC) that occur after playButton is pressed, then that may explain why the it is becoming disabled upon return from background. Why? I don't know. But I had a similar issue and resolved it by creating a new class and VC for the multiple animations that were originally set to occur when my UIButton was pressed. Inside of my button's IBAction, I simply created a segue to then new VC.

    With regards to the animation, you could approach this two ways: 1) Pause and Resume the animation using CALayer OR 2) Simply use NotificationCenter without even having to touch any AppDelegate code. I prefer simple ways b/c it will save time and effort. So, try this code in the VC where the button animation is to occur:

    override func viewWillAppear(_ animated: Bool) {
    
        NotificationCenter.default.addObserver(self, selector:#selector(goingToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
    
        NotificationCenter.default.addObserver(self, selector:#selector(openingApp), name: UIApplication.willEnterForegroundNotification, object: nil)
    
    
    
        UIView.animate(withDuration: 1.0,
                        delay: 0,
                        options: [.autoreverse, .repeat, .allowUserInteraction],
                        animations: {
                            self.playButton.transform = CGAffineTransform(scaleX: 1.175, y: 1.175)
                        },
                        completion: nil)
    }
    
    @objc func goingToBackground(){
        playButton.transform = .identity
    }
    
    @objc func openingApp(){
        self.view.layoutIfNeeded()
        UIView.animate(withDuration: 1.0,
                       delay: 0.3,
                       options: [.autoreverse, .repeat, .allowUserInteraction],
                       animations: {
                        self.playButton.transform = CGAffineTransform(scaleX: 1.175, y: 1.175)}, completion: nil)
        self.view.layoutIfNeeded()
    
    }