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

孤者浪人 提交于 2020-12-12 05:12:32

问题


I'm using SwiftUI's new app lifecycle coming in iOS 14.

However, I'm stuck at how to access my AppState (single source of truth) object in the AppDelegate. I need the AppDelegate to run code on startup and register for notifications (didFinishLaunchingWithOptions, didRegisterForRemoteNotificationsWithDeviceToken, didReceiveRemoteNotification) etc.

I am aware of @UIApplicationDelegateAdaptor but then I can not e.g. pass an object through to the AppDelegate with a constructor. I guess the other way round (creating the AppState in the AppDelegate and then accessing it in MyApp) does not work either.

@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()
}

Any help is appreciated. Maybe there is currently no way to achieve this, and I need to convert my app to use the old UIKit lifecycle?


回答1:


Use shared instance for AppState

class AppState: ObservableObject {
    static let shared = AppState()    // << here !!

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

so you can use it everywhere

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

    // ... other code
}

and

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

        AppState.shared.user = ...
    }



回答2:


Is there a reason why you need to run the code in app delegate? If you are using new app lifecycle, why not trigger your code from 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



来源:https://stackoverflow.com/questions/63597783/accessing-appstate-in-appdelegate-with-swiftuis-new-ios-14-life-cycle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!