Why does viewWillAppear not get called when an app comes back from the background?

Swift

Short answer

Use a NotificationCenter observer rather than viewWillAppear.

override func viewDidLoad() {
    super.viewDidLoad()

    // set observer for UIApplication.willEnterForegroundNotification
    NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)

}

// my selector that was defined above
@objc func willEnterForeground() {
    // do stuff
}

Long answer

To find out when an app comes back from the background, use a NotificationCenter observer rather than viewWillAppear. Here is a sample project that shows which events happen when. (This is an adaptation of this Objective-C answer.)

import UIKit
class ViewController: UIViewController {

    // MARK: - Overrides

    override func viewDidLoad() {
        super.viewDidLoad()
        print("view did load")

        // add notification observers
        NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)

    }

    override func viewWillAppear(_ animated: Bool) {
        print("view will appear")
    }

    override func viewDidAppear(_ animated: Bool) {
        print("view did appear")
    }

    // MARK: - Notification oberserver methods

    @objc func didBecomeActive() {
        print("did become active")
    }

    @objc func willEnterForeground() {
        print("will enter foreground")
    }

}

On first starting the app, the output order is:

view did load
view will appear
did become active
view did appear

After pushing the home button and then bringing the app back to the foreground, the output order is:

will enter foreground
did become active 

So if you were originally trying to use viewWillAppear then UIApplication.willEnterForegroundNotification is probably what you want.

Note

As of iOS 9 and later, you don’t need to remove the observer. The documentation states:

If your app targets iOS 9.0 and later or macOS 10.11 and later, you
don’t need to unregister an observer in its dealloc method.

Leave a Comment