将 Firebase 身份验证与新的 @App 协议一起使用

Posted

技术标签:

【中文标题】将 Firebase 身份验证与新的 @App 协议一起使用【英文标题】:Using Firebase Authentication with new @App protocol 【发布时间】:2020-12-16 19:38:28 【问题描述】:

我是 ios 开发新手,正在努力使用 SwiftUI 中的新 @App 协议实现 Firebase 手机身份验证。 Firebase 的文档是为 UIKit 编写的,SwiftUI 的在线教程使用 AppDelegate 和 SceneDelegate 而不是 App 结构中的新 @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.

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

【问题讨论】:

您不需要 AppDelegate。在 MapworkApp.swift 文件中,添加一个 init() 函数并在 init 中调用 FirebaseApp.configure()。 当我尝试这个时,我收到一个编译器错误,“init cannot be used as a keyword here” init() 是一个函数。它应该看起来像: init() FirebaseApp.configure() ... 把它放在身体外面。 不幸的是,在这样做之后,我仍然收到上面相同的运行时错误。还是谢谢你的帮助。 【参考方案1】:

对于许多 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 and the new SwiftUI 2 Application Life Cycle - SwiftUI 2 The Ultimate Guide to the SwiftUI 2 Application Life Cycle - SwiftUI 2

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

【讨论】:

以上是关于将 Firebase 身份验证与新的 @App 协议一起使用的主要内容,如果未能解决你的问题,请参考以下文章

Expo App 中的 Firebase 无密码电子邮件身份验证错误

如何将多个身份验证提供程序链接到 Firebase 帐户?

Firebase 身份验证单元测试错误 No Firebase App

我应该如何为 Firebase 身份验证创建新的联合身份提供程序

由于 Firebase 手机身份验证,App Store 被拒绝

Firebase 安全性和电话身份验证