处理 SwiftUI 组合应用程序中的 Firebase 身份验证错误

Posted

技术标签:

【中文标题】处理 SwiftUI 组合应用程序中的 Firebase 身份验证错误【英文标题】:Handling Firebase Auth error in SwiftUI Combine app 【发布时间】:2020-02-12 22:52:00 【问题描述】:

我有一个应用,用户可以在其中使用 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 didSetdidChange.send() 
@Published var isNewUser = false didSetdidChange.send() 
@Published var failedToCreateAccount = false didSetdidChange.send() 
@Published var failedToLogin = false didSetdidChange.send() 
@Published var errorMessage = "" didSetdidChange.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 错误信息不显示;登录视图也显示在主视图之前。

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

【问题讨论】:

问题似乎是userStore.login 是一个异步过程。 IE。对if self.userStore.failedToLogin 的调用在userStore.login 返回之前执行。因此,userStore.failedToLogin 仍然是false,条件语句中的代码永远不会被执行。有两种方法可以解决这个问题:1. 在userStore.logIn 上实现一个尾随闭包,并将显示错误的代码移动到闭包中 2. 使userStore.failedToLogin 成为发布者并订阅您的警报的可见性 @PeterFriese 100% 点评论。我会将其发布为答案。 OP - 此行 self.isLoggingIn = true 及其后面的代码将在用户登录之前执行 - 代码比互联网快,您需要从 Firebase 登录闭包中执行下一个“步骤” .请参阅我对this question 的回复以获取更多信息 pod 'CombineFirebase/Auth' 将极大地简化您的问题。除了回调,您可以简单地使用组合发布者模式并使用组合强大的运算符。 【参考方案1】:

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

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

有两种解决方法:

    userStore.logIn 上实现一个尾随闭包,并将显示错误的代码移到闭包中 将userStore.failedToLogin 设为发布者并订阅您的警报的可见性给它

【讨论】:

非常感谢!是的,现在很明显。我还阅读了您关于 Firebase 和 SwiftUI 的 Medium 帖子,Combine;知道 Apple 登录的第 3 部分什么时候出吗?因为这就是我现在正在做的事情.. 感谢@RileyDev 的客气话!在我们说话的同时进行第 3 部分,希望下周能完成! @RileyDev 询问的系列的第 3 部分现已在 peterfriese.dev/replicating-reminder-swiftui-firebase-part3 上提供【参考方案2】:

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

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

【讨论】:

以上是关于处理 SwiftUI 组合应用程序中的 Firebase 身份验证错误的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 SwiftUI 中的组合框架从 Spotify API 获取数据

SwiftUI URLImage 水平滚动视图

SwiftUI - 等到 Firestore getDocuments() 完成后再继续

SwiftUI之深入解析如何创建和组合视图

SwiftUI:视图组合的代码重用

SwiftUI 和具有 @Published 的组合 Observable 对象不断发布