【问题标题】:Accessing AppState in AppDelegate with SwiftUI's new iOS 14 life cycle使用 SwiftUI 的 iOS 14 新生命周期访问 AppDelegate 中的 AppState
【发布时间】:2020-12-15 06:18:21
【问题描述】:

我正在使用 iOS 14 中即将推出的 SwiftUI 新应用生命周期。

但是,我不知道如何在 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 生命周期?

【问题讨论】:

    标签: swift swiftui state appdelegate ios14


    【解决方案1】:

    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 = ...
        }
    

    【讨论】:

    • 这是一个很好的方法,那么在 AppDelegate 中操作共享对象呢,@StateObject 变量是否会向视图发出更新?
    • 是的,SwiftUI 2.0 StateObject 正是为此目的。
    【解决方案2】:

    您是否需要在应用委托中运行代码? 如果你正在使用新的应用生命周期,为什么不从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

    【讨论】:

    • 感谢您的评论!我需要为didRegisterForRemoteNotificationsWithDeviceTokendidReceiveRemoteNotification 运行代码,如果我没记错的话,它们只有在 AppDelegate 中可用?
    • @Mister22,如果这是您的用例,我认为 Asperi 的解决方案是一个合理的解决方案。我想我个人也会走这条路。
    猜你喜欢
    • 2021-03-31
    • 2020-10-15
    • 2020-10-13
    • 2020-02-26
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多