SwiftUI App lifecycle

Is there a way to handle events that were in UIApplicationDelegate or UISceneDelegate in SwiftUI App lifecycle?

With ScenePhase you can access the different states of the app as done previously in SceneDelegate

Code Block
@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of: scenePhase) { phase in
            switch phase {
            case .active:
            print("Active")
            case .inactive:
                print("Inactive")
            case .background:
                print("Background")
            @unknown default:
                print("Unknown")
            }
        }
    }
}


You can also use the @UIApplicationDelegateAdaptor property wrapper if you prefer the UIKit way.

Code Block swift
@main
struct SampleApp: App {
    @UIApplicationDelegateAdaptor var delegate: AppDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print(#function)
        return true
    } 
}

@Volker88 is totally right, you have to add @Environment(\.scenePhase) var scenePhase. So the full example should be:

Code Block swift
import SwiftUI
@main
struct TestApp: App {
    @Environment(\.scenePhase) var scenePhase
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of: scenePhase) { phase in
            switch phase {
            case .active:
            print("Active")
            case .inactive:
                print("Inactive")
            case .background:
                print("Background")
            @unknown default:
                print("Unknown")
            }
        }
    }
}

I have tried the multiple options so far. That entire .onChange seems like a bolt-on afterthought to be honest. I am sure it will work great in the future, but for now, it's not only not being called when you follow the examples (you must put it in a View), but it only gets called on change, doesn't have the initial launch, final termination, and will not help transitions between scenes either.

So for the time being, the .onChange would be good for the View, but would get called independently on every single instance of the app, which is not good if you have a central model expecting one single call.

And as described by @mtsrodrigues, you can create an AppDelegate, which will work good. But you don't have access to the App stack, you must make it go through hoops to get it and get your model, which might not be what you actually want. To get non-hackish, you'd put your app model in your AppDelegate, and have your view model caches registering to your AppDelegate so they'd get called on events, which is not what is expected.

So far, the best solution I found was to go on the different sites of my model where the App-wide delegation happens, and add Notification observers for each site. Bonus is it makes your code truly modular. Malus is they haven't yet created a SwiftUI-compatible platform-agnostic version, so you must ifdef your way.

Here is my code in my AppEnvironment @State object, that's now residing as a singleton in my App. (Please note my final version has all this code - and much more - directly in store and photoLibrary as there's no reason to centralize it)

Code Block swift
        #if os(macOS)
        NotificationCenter.default.addObserver(
            forName: NSApplication.didFinishLaunchingNotification,
            object: nil,
            queue: .main)
        { [weak self] notification in
            self?.store.enabled = true
        }
        NotificationCenter.default.addObserver(
            forName: NSApplication.willTerminateNotification,
            object: nil,
            queue: .main)
        { [weak self] notification in
            self?.store.enabled = false
        }
        #else
        NotificationCenter.default.addObserver(
            forName: UIApplication.didFinishLaunchingNotification,
            object: nil,
            queue: .main)
        { [weak self] notification in
            self?.store.enabled = true
        }
        NotificationCenter.default.addObserver(
            forName: UIApplication.willTerminateNotification,
            object: nil,
            queue: .main)
        { [weak self] notification in
            self?.store.enabled = false
        }
        NotificationCenter.default.addObserver(
            forName: UIApplication.didReceiveMemoryWarningNotification,
            object: nil,
            queue: .main)
        { [weak self] notification in
            self?.photoLibrary.clearCache()
        }
        #endif


SwiftUI App lifecycle
 
 
Q