使用 SwiftUI 的新 iOS 14 生命周期访问 AppDelegate 中的 AppState

Accessing AppState in AppDelegate with SwiftUI's new iOS 14 life cycle

我正在使用 SwiftUI 的新应用程序生命周期 iOS 14.

但是,我一直不知道如何在 AppDelegate 中访问我的 AppState(单一事实来源)对象。 我在启动时需要 AppDelegate 到 运行 代码并注册通知(didFinishLaunchingWithOptionsdidRegisterForRemoteNotificationsWithDeviceTokendidReceiveRemoteNotification)等

我知道 @UIApplicationDelegateAdaptor 但我不能,例如使用构造函数将对象传递给 AppDelegate。我想反过来(在 AppDelegate 中创建 AppState,然后在 MyApp 中访问它)也不行。

@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @State var appState = AppState()
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(appState)
        }
    }
}
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // access appState here...
        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // ...and access appState here
    }
}
class AppState: ObservableObject {
    // Singe source of truth...
    @Published var user: User()
}

感谢任何帮助。也许目前没有办法实现这一点,我需要转换我的应用程序以使用旧的 UIKit 生命周期?

AppState

使用共享实例
class AppState: ObservableObject {
    static let shared = AppState()    // << here !!

    // Singe source of truth...
    @Published var user = User()
}

所以你可以在任何地方使用它

struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @StateObject var appState = AppState.shared

    // ... other code
}

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // ...and access appState here

        AppState.shared.user = ...
    }

backup

您需要 运行 应用程序委托中的代码的原因是什么? 如果您正在使用新的应用程序生命周期,为什么不从 WindowGroup.onChange()

触发您的代码
struct MyScene: Scene {
    @Environment(\.scenePhase) private var scenePhase
    @StateObject private var cache = DataCache()

    var body: some Scene {
        WindowGroup {
            MyRootView()
        }
        .onChange(of: scenePhase) { newScenePhase in
            if newScenePhase == .background {
                cache.empty()
            }
        }
    }
}

Apple Documentation Link

Managing scenes in SwiftUI by Majid