2

I am creating a cross-platform app with SwiftUI 2.0. The app's lifecycle is managed by SwiftUI, so there is no app or scene delegate. If possible, I would like to keep it that way. In order to persist data when the app quits or enters the background, I am watching for changes on scenePhase.

@main
struct MyApp: App {
    
    @Environment(\.scenePhase) var scenePhase
    @StateObject var dataModel = DataModel()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onChange(of: scenePhase) { newScenePhase in
                    switch newScenePhase {
                    case .background, .inactive:
                        dataModel.save()
                    default: break
                }
        }
    }
}

However, this approach has an inherent flaw: on macOS, when the app is terminated, there is no change in scenePhase, and thus the data is not persisted. Is there a separate mechanism for detecting app termination? Does SwiftUI have the equivalent of applicationWillTerminate:?

Jacob
  • 402
  • 3
  • 14

2 Answers2

2

You can inject application delegate via adapter. Use as the following example:

#if os(macOS)
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }
}
#endif

@main
struct MyApp: App {

#if os(macOS)
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#endif

    // ... other code
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • How would I go about passing my model object through the `@ NSApplicationDelegateAdaptor` so that I can access its properties through the app delegate? – Jacob Nov 22 '20 at 05:06
  • One question - one answer, and that's different question... you can find answer in https://stackoverflow.com/a/63597866/12299030. – Asperi Nov 22 '20 at 05:12
  • @Asperi: can I use `NSAlert.runModal()` to display a user message box in `applicationWillTerminate` and then prevent the app from closing upon user selection? – c00000fd Apr 04 '23 at 19:39
1

Use this in App:

.onReceive(NotificationCenter.default.publisher(for: NSApplication.willTerminateNotification)) { _ in
    // tear down
}
soundflix
  • 928
  • 9
  • 22