在 StateObject 初始化之前在应用程序委托中进行 Firebase 初始化
Firebase initialisation in application delegate before StateObject initialisation
我正在用 SwiftUI 编写应用程序并使用 Firebase 作为我的后端。
我有一个工作首选项面板,它由应用程序本身内的一个模式组成,但我想利用 macOS 的一致首选项 window,其中包括菜单选项以及写在 this文章。
这是我的应用声明和委托。
@main
struct SchedulerApp: App {
#if os(macOS)
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#else
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#endif
@StateObject var authState = AuthState()
@StateObject var model = Model()
var body: some Scene {
WindowGroup {
ContentView()
.frame(minWidth: 800, minHeight: 450)
.environmentObject(model)
.environmentObject(authState)
}
.commands {
SidebarCommands()
}
#if os(macOS)
Settings {
Preferences()
}
#endif
}
}
#if os(macOS)
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationWillFinishLaunching(_ notification: Notification) {
FirebaseApp.configure()
}
}
#else
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
#endif
您可以看到我有一个委托和一个状态对象,一个对象侦听身份验证状态,另一个对象保存用户数据和设置:
class AuthState: ObservableObject {
var handle: AuthStateDidChangeListenerHandle?
@Published var signedIn: Bool? = nil
init() {
listen()
}
func listen() {
Auth.auth().addStateDidChangeListener { [self] (auth, user) in
switch user == nil {
case true: signedIn = false
case false: signedIn = true
}
}
}
}
但是,当我运行这段代码时,出现如下错误:
The default Firebase app has not yet been configured. Add [FIRApp configure];
(FirebaseApp.configure()
in Swift) to your application initialization. Read more: (...)
The default FIRApp instance must be configured before the default FIRAuthinstance can be initialized. One way to ensure that is to call [FIRApp configure];
(FirebaseApp.configure()
in Swift) in the App Delegate's application:didFinishLaunchingWithOptions:
(application(_:didFinishLaunchingWithOptions:)
in Swift).
我需要应用程序在初始化步骤有一个单一的真实来源 - 但 applicationWillFinishLaunching 出于某种原因在 StateObject 调用之后调用。
我的应用目前在 ContentView 中声明了这些 StateObject 类,这避免了这些错误,但正如我上面提到的,我需要偏好来共享单一的真实来源。
非常感谢任何帮助!
在 SchedulerApp 中:应用程序只需添加一个 init 来初始化 Firebase。您将不再需要 AppDelegate class(除非您稍后要在那里做其他事情)。
init() {
FirebaseApp.configure()
}
如 中所述,您可以使用应用的初始化程序 (init()
) 或 AppDelegate
来初始化 Firebase。
使用初始化程序适用于相当多的 Firebase SDK,但也有一些使用方法调配,并且他们希望存在 AppDelegate
.
在 The Ultimate Guide to the SwiftUI 2 Application Life Cycle - SwiftUI 2 中,我深入探讨了新应用程序生命周期的一些细节。
让我们看一下我为那篇文章构建的 sample app 的代码,以及生成的输出:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("Colors application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.")
return true
}
}
@main
struct ColorsApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
@Environment(\.scenePhase) var scenePhase
init() {
print("Colors application is starting up. App initialiser.")
}
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("Oh - interesting: I received an unexpected new value.")
}
}
}
}
调试控制台输出:
Colors application is starting up. App initialiser.
Colors application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.
App is active
所以应用初始化如下:
- 调用了应用程序初始化程序
AppDelegate
的didFinishLaunchingWithOptions
被称为
scenePhase
变为.active
对于您的应用,我建议如下:
- 在您应用的初始化程序中初始化 Firebase
- 在您应用的初始化程序中,初始化您的模型和其他真实来源,并将它们连接到相应的 Firebase 服务
另一种选择是:
- 在您应用的初始化程序中初始化 Firebase
- 通过提供默认值(就像您所做的那样)初始化您的模型和事实来源,但暂时不要连接到 Firebase
- 实施
ScenePhase
处理程序,并且 - 一旦应用程序进入 .active
状态,“激活”您的模型并告诉它们连接到 Firebase。
第一个选项听起来更简洁,也更容易实施。对我来说:-)
我正在用 SwiftUI 编写应用程序并使用 Firebase 作为我的后端。
我有一个工作首选项面板,它由应用程序本身内的一个模式组成,但我想利用 macOS 的一致首选项 window,其中包括菜单选项以及写在 this文章。
这是我的应用声明和委托。
@main
struct SchedulerApp: App {
#if os(macOS)
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#else
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#endif
@StateObject var authState = AuthState()
@StateObject var model = Model()
var body: some Scene {
WindowGroup {
ContentView()
.frame(minWidth: 800, minHeight: 450)
.environmentObject(model)
.environmentObject(authState)
}
.commands {
SidebarCommands()
}
#if os(macOS)
Settings {
Preferences()
}
#endif
}
}
#if os(macOS)
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationWillFinishLaunching(_ notification: Notification) {
FirebaseApp.configure()
}
}
#else
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
#endif
您可以看到我有一个委托和一个状态对象,一个对象侦听身份验证状态,另一个对象保存用户数据和设置:
class AuthState: ObservableObject {
var handle: AuthStateDidChangeListenerHandle?
@Published var signedIn: Bool? = nil
init() {
listen()
}
func listen() {
Auth.auth().addStateDidChangeListener { [self] (auth, user) in
switch user == nil {
case true: signedIn = false
case false: signedIn = true
}
}
}
}
但是,当我运行这段代码时,出现如下错误:
The default Firebase app has not yet been configured. Add
[FIRApp configure];
(FirebaseApp.configure()
in Swift) to your application initialization. Read more: (...)
The default FIRApp instance must be configured before the default FIRAuthinstance can be initialized. One way to ensure that is to call
[FIRApp configure];
(FirebaseApp.configure()
in Swift) in the App Delegate'sapplication:didFinishLaunchingWithOptions:
(application(_:didFinishLaunchingWithOptions:)
in Swift).
我需要应用程序在初始化步骤有一个单一的真实来源 - 但 applicationWillFinishLaunching 出于某种原因在 StateObject 调用之后调用。
我的应用目前在 ContentView 中声明了这些 StateObject 类,这避免了这些错误,但正如我上面提到的,我需要偏好来共享单一的真实来源。
非常感谢任何帮助!
在 SchedulerApp 中:应用程序只需添加一个 init 来初始化 Firebase。您将不再需要 AppDelegate class(除非您稍后要在那里做其他事情)。
init() {
FirebaseApp.configure()
}
如 init()
) 或 AppDelegate
来初始化 Firebase。
使用初始化程序适用于相当多的 Firebase SDK,但也有一些使用方法调配,并且他们希望存在 AppDelegate
.
在 The Ultimate Guide to the SwiftUI 2 Application Life Cycle - SwiftUI 2 中,我深入探讨了新应用程序生命周期的一些细节。
让我们看一下我为那篇文章构建的 sample app 的代码,以及生成的输出:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("Colors application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.")
return true
}
}
@main
struct ColorsApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
@Environment(\.scenePhase) var scenePhase
init() {
print("Colors application is starting up. App initialiser.")
}
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("Oh - interesting: I received an unexpected new value.")
}
}
}
}
调试控制台输出:
Colors application is starting up. App initialiser.
Colors application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.
App is active
所以应用初始化如下:
- 调用了应用程序初始化程序
AppDelegate
的didFinishLaunchingWithOptions
被称为scenePhase
变为.active
对于您的应用,我建议如下:
- 在您应用的初始化程序中初始化 Firebase
- 在您应用的初始化程序中,初始化您的模型和其他真实来源,并将它们连接到相应的 Firebase 服务
另一种选择是:
- 在您应用的初始化程序中初始化 Firebase
- 通过提供默认值(就像您所做的那样)初始化您的模型和事实来源,但暂时不要连接到 Firebase
- 实施
ScenePhase
处理程序,并且 - 一旦应用程序进入.active
状态,“激活”您的模型并告诉它们连接到 Firebase。
第一个选项听起来更简洁,也更容易实施。对我来说:-)