Triggering a specific action when the app enters foreground from a local notification in iOS? (using swift)

If I want a view controller to be notified when the app is brought back to the foreground, I might just register for the UIApplication.willEnterForegroundNotification notification (bypassing the app delegate method entirely):

class ViewController: UIViewController {

    private var observer: NSObjectProtocol?

    override func viewDidLoad() {
        super.viewDidLoad()

        observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [unowned self] notification in
            // do whatever you want when the app is brought back to the foreground
        }
    }

    deinit {
        if let observer = observer {
            NotificationCenter.default.removeObserver(observer)
        }
    }
}

Note, in the completion closure, I include [unowned self] to avoid strong reference cycle that prevents the view controller from being deallocated if you happen to reference self inside the block (which you presumably will need to do if you're going to be updating a class variable or do practically anything interesting).

Also note that I remove the observer even though a casual reading of the removeObserver documentation might lead one to conclude is unnecessary:

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.

But, when using this block-based rendition, you really do need to remove the notification center observer. As the documentation for addObserver(forName:object:queue:using:) says:

To unregister observations, you pass the object returned by this method to removeObserver(_:). You must invoke removeObserver(_:) or removeObserver(_:name:object:) before any object specified by addObserver(forName:object:queue:using:) is deallocated.


I like to use the Publisher initializer of NotificationCenter. Using that you can subscribe to any NSNotification using Combine.


import UIKit
import Combine

class MyFunkyViewController: UIViewController {

    /// The cancel bag containing all the subscriptions.
    var cancelBag = [AnyCancellable]()

    override func viewDidLoad() {
        super.viewDidLoad()
        addSubscribers()
    }

    /// Adds all the subscribers.
    private func addSubscribers() {
        NotificationCenter
            .Publisher(center: .default,
                       name: UIApplication.willEnterForegroundNotification)
            .sink { [weak self] _ in
                self?.doSomething()
            }
            .store(in: &cancelBag)
    }

    /// Called when entering foreground.
    private func doSomething() {
        print("Hello foreground!")
    }
}