处理 SwiftUI Combine 应用程序中的 Firebase Auth 错误

Handling Firebase Auth error in SwiftUI Combine app

我有一个应用程序,用户可以在其中使用 Firebase 进行注册和登录。但是,我似乎无法提醒用户视图中的任何错误。

首先我们有一个 UserStore,它是一个 ObservableObject,在 SceneDelegate 中设置视图时被初始化为 EnvironmentObject .

let appView = AppView().environmentObject(userStore)

  if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: appView)
        self.window = window
        window.makeKeyAndVisible()

}

然后我们像这样注册或登录到视图。

在视图中

self.userStore.logIn(email: self.email, password: self.password)
self.isLoggingIn = true

if self.userStore.failedToLogin {
   self.isLoggingIn = false
   self.alertTitle = "There seems to be a problem"
   self.alertBody = self.userStore.errorMessage
   self.showingAlert = true
}

然后实际方法应该更新 UserStore 属性 值,然后更新视图并显示警报,但是,情况并非如此。

登录

// Session Properties
@Published var isLoggedIn = false {didSet{didChange.send() }}
@Published var isNewUser = false {didSet{didChange.send() }}
@Published var failedToCreateAccount = false {didSet{didChange.send() }}
@Published var failedToLogin = false {didSet{didChange.send() }}
@Published var errorMessage = "" {didSet{didChange.send() }}

init () {
  handle = Auth.auth().addStateDidChangeListener { (auth, user) in
    if let user = user {
      self.session = user
      self.isLoggedIn = true
      //Change isNewUser is user document exists?
   } else {
      self.session = nil
      self.isLoggedIn = false
    }
  }
}

func logIn(email: String, password: String) {

    Auth.auth().signIn(withEmail: email, password: password) { [weak self] user, error in

        print("Signed In")

        if(error != nil) {
            print("Failed to login")

            self!.failedToLogin = true
            self!.errorMessage = ("\(String(describing: error))")
            print(error!)
            return
        } else if error == nil {
            print("Success Logging In")

        }
    }
}

AppView 根据用户是否登录决定加载哪个视图。

AppView

        if !userStore.isLoggedIn {
            LoginView().transition(.opacity)
        }

        if userStore.isLoggedIn  {
            ContentView().transition(.opacity)
        }

未显示 Atm 错误消息;登录视图也在主视图之前不久显示。

如何在视图中正确显示错误消息?

Firebase API 是异步的,因为它们通过互联网访问远程系统,这需要一点时间。顺便说一句,这同样适用于访问本地磁盘。 blog post 对此进行了更详细的解释。

因此,userStore.login 是一个异步过程。 IE。对 if self.userStore.failedToLogin 的调用在 userStore.login returns 之前执行。因此,userStore.failedToLogin仍然是false,条件语句中的代码永远不会执行。

有两种解决方法:

  1. userStore.logIn 上实现尾随闭包,并将显示错误的代码移至闭包
  2. 创建 userStore.failedToLogin 发布者并订阅您的快讯的可见性

使用 Combine Firebase:https://github.com/rever-ai/CombineFirebase

这是围绕 firebase api 的 combine-swiftui 包装器,因此您可以对 firebase 使用 swift-ui 发布者模式。