UIApplication.willEnterForegroundNotification not fired when Notification Center puts app in background

Using addObserver func of NotificationCenter.default, subscribing to UIApplication.willEnterForegroundNotification does not work when the backgrounding is triggered from Notification Center (swipe down from top when app is active to get Notification Center).  It also seems that UIApplication.willResignActiveNotification is called twice, based on Print() logs, when Notification Center triggers the backgrounding.

If you background the app via lock screen or manual swipe, or switch to another app, the UIApplication.willEnterForegroundNotification does get called, so it seems to be specific to Notification Center.

UIApplication.willResignActiveNotification does fire correctly but then resuming the app never calls the appMovedToForeground func below:

notificationCenter.addObserver(self, selector: #selector(appMovedToForeground), name: UIApplication.willEnterForegroundNotification,object: nil)

occurs on: iOS 14.4.2, iPhone 11 & iOS 14.6, SE(2)

Accepted Reply

UIApplication.willEnterForegroundNotification is posted when the application transitions to the foreground state. Note that this is not the active state.

https://developer.apple.com/documentation/uikit/uiapplication/state/

Being foreground translates to: UIApplication.State.inactive as well as UIApplication.State.active. The application is foreground in both states, but when inactive there is something (or somethings) preventing it from being active.

So when Control Center or Notification Center are presented, it would be expected that the application state moves to inactive, and UIApplication.willResignActiveNotification is posted. When those issues are resolved, it would be expected that UIApplication.didBecomeActiveNotification is posted, not UIApplication.willEnterForegroundNotification.

Replies

UIApplication.willEnterForegroundNotification is posted when the application transitions to the foreground state. Note that this is not the active state.

https://developer.apple.com/documentation/uikit/uiapplication/state/

Being foreground translates to: UIApplication.State.inactive as well as UIApplication.State.active. The application is foreground in both states, but when inactive there is something (or somethings) preventing it from being active.

So when Control Center or Notification Center are presented, it would be expected that the application state moves to inactive, and UIApplication.willResignActiveNotification is posted. When those issues are resolved, it would be expected that UIApplication.didBecomeActiveNotification is posted, not UIApplication.willEnterForegroundNotification.

Ahh, thanks for the clarification. Working now.

my 2 cents for SwiftUI in a cross platform way (Hope help others)


import SwiftUI

#if os(iOS)
import UIKit
#elseif os(macOS)
import AppKit
#endif


struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .onAppEnteredBackground {
            print("going back")
        }
    }
}

//MARK: extension


#if os(iOS)
fileprivate let GO_DOWN = UIApplication.didEnterBackgroundNotification
#elseif os(macOS)
fileprivate let GO_DOWN = NSApplication.didResignActiveNotification
#endif



extension View {
    
    func onNotification(
        _ notificationName: Notification.Name,
        perform action: @escaping () -> Void
    ) -> some View {
        onReceive(NotificationCenter.default.publisher(
            for: notificationName
        )) { _ in
            action()
        }
    }
    
    func onAppEnteredBackground(
        perform action: @escaping () -> Void
    ) -> some View {
        onNotification(
            GO_DOWN,
            perform: action
        )
    }
}