Peter Kreinz
Peter Kreinz

Reputation: 8666

How to Listen to new SwiftUI Lifecycle Methods in iOS 14?

To reduce boilerplate code, I want to use the new SwiftUI Lifecycle in iOS 14 to replace AppDelegate and SceneDelegate. But how to Listen to SceneDelegate Lifecycle Methods?

For example:

How to save changes in the application's managed object context when the application transitions to the background?

import SwiftUI
    
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    let persistenceController = PersistenceController.shared

    ...

    func sceneDidEnterBackground(_ scene: UIScene) {
        persistenceController.saveContext()
    }
}

Upvotes: 2

Views: 878

Answers (2)

LukeSideWalker
LukeSideWalker

Reputation: 7930

You can get the APP LAUNCHING STATES (formerly done in AppDelegate) by being notified from the global environment variable and its property ".scenePhase" like so:

// CREATE SOME APP LAUNCHING STATES LIKE WE HAD IN APPDELEGATE

@main
struct NewAppLifeCycleApp: App {

  @Environment(\.scenePhase) var scenePhase
  
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
    .onChange(of: scenePhase) { newScenePhase in
      switch newScenePhase {
      case .active:
        print("App is active")
      case .inactive:
        print("App is inactive")
      case .background:
        print("App is in background")
      @unknown default:
        print("Interesting: Unexpected new value.")
      }
    }
  }
}

If you want to integrate some code at a very early stage of your app, you can just add an init-function:

// EASY WAY TO INTEGRATE SOME CODE INTO 
// VERY EARLY STAGE OF APP INIT

@main
struct ColorsApp: App {

  // Add an init method to add code
  init() { print("My App is starting") }
  
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
}

Upvotes: 4

Peter Kreinz
Peter Kreinz

Reputation: 8666

I could help myself.

To listen to lifecycle updates, as we do in SceneDelegate, a scenePhase enumerator holds the current state of the scene. We can use it as an Environment-Property-Wrapper and listen to state changes:

import SwiftUI

@main
struct MyiOS14App: App {
    
    @Environment(\.scenePhase) private var scenePhase

    let persistenceController = PersistenceController.shared
    
    var body: some Scene {

        WindowGroup {
            ContentView()
        }
        .onChange(of: scenePhase) { (phase) in
            switch phase {
            case .active:
                break

            case .background:
                //perform cleanup
                break

            case .inactive:
                persistenceController.saveContext()
                
            @unknown default:
                fatalError()
            }
        }
    }
}

Upvotes: 2

Related Questions