将Firebase身份验证与新的@App协议结合使用



我是iOS开发的新手,正在努力在SwiftUI中使用新的@App协议实现Firebase手机身份验证。Firebase的文档是为UIKit编写的,SwiftUI的在线教程使用AppDelegate和SceneDelegate,而不是应用程序结构中的新@main协议。

我的具体问题如下:我将如何/在哪里注入我创建的身份验证状态类?

import Foundation
class AuthenticationState: NSObject,  ObservableObject
{
@Published var loggedInUser: User?
@Published var isAuthenticating = false
@Published var error: NSError?

static let shared = AuthenticationState();

private let auth = Auth.auth();
fileprivate var currentNonce: String?

func login(with loginOption: LoginOption) {
self.isAuthenticating = true
self.error = nil
switch loginOption {
case .signInWithApple:
handleSignInWithApple()
}
}
func signup(email: String, password: String, passwordConfirmation: String) {
// TODO
}
private func handleSignInWithApple() {
// TODO
}
}

其次,AuthenticationState类不知道Firebase Auth对象,我认为这是因为它的配置不正确。到目前为止,我正在AppDelegate类中配置Firebase:

import UIKit
import Firebase

class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()


return true
}




}

然而,我还有一个MapworkApp.swift文件,我认为它应该取代AppDelegate,但我不确定:

import SwiftUI
import Firebase
@main
struct MapworkApp: App {
let persistenceController = PersistenceController.shared
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

var body: some Scene {
WindowGroup {
ContentView()
.environment(.managedObjectContext, persistenceController.container.viewContext)
}
}
}
struct MapworkApp_Previews: PreviewProvider {
static var previews: some View {
/*@START_MENU_TOKEN@*/Text("Hello, World!")/*@END_MENU_TOKEN@*/
}
}

我目前收到的运行时错误:

020-12-16 13:22:34.416917-0700 Mapwork[1351:332863] 7.3.0 - [Firebase/Core][I-COR000003] The default Firebase app has not yet been configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your application initialization. Read more: 
2020-12-16 13:22:34.417240-0700 Mapwork[1351:332633] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '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).'
*** First throw call stack:
(0x1863a586c 0x19b314c50 0x18629e4a4 0x102bc8918 0x1028465d8 0x1028466f4 0x102845c1c 0x102845be4 0x102ec96c0 0x102ecb1f8 0x18a32c5bc 0x102845c64 0x102854aa0 0x102854cbc 0x18cdba724 0x102854c18 0x102855028 0x185fda6b0)
libc++abi.dylib: terminating with uncaught exception of type NSException
terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '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).'
Message from debugger: The LLDB RPC server has exited unexpectedly. Please file a bug if you have reproducible steps.

任何帮助或指导都将不胜感激,因为在线文档现在不适用。

对于许多Firebase API,您不需要使用AppDelegate方法。相反,你可以在应用程序的初始化程序中初始化Firebase,就像这样:

import SwiftUI
import Firebase
@main
struct MapworkApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

这适用于使用Cloud Firestore和Firebase身份验证(使用Apple登录(的应用程序。

对于Firebase的某些SDK,您需要实现一个AppDelegate。要做到这一点,请像这样实现AppDelegate

class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("Application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.")
return true
}

// ... add any callbacks your app might require
}

然后,将您的App连接到AppDelegate,如下所示:

@main
struct MapworkApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

init() {
FirebaseApp.configure()
}

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

您可能需要将呼叫从FirebaseApp.configure()移动到AppDelegate。在这种情况下,您的AppDelegateApp可能是这样的(如果您愿意,可以将它们保存在同一个文件中(:

class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
return true
}
}
@main
struct MapworkApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

要了解更多信息,请查看我关于新应用程序生命周期的文章:

  • Firebase和新的SwiftUI 2应用程序生命周期-SwiftUI 2
  • SwiftUI 2应用程序生命周期的终极指南-SwiftUI 2

我编写的这个示例应用程序展示了如何使用SwiftUI和Firebase构建一个简单的待办事项列表应用程序:peterfreese/MakeItSo。最新版本的代码遵循新的SwiftUI 2应用程序生命周期,并包括使用Apple登录

最新更新