【问题标题】:Using completion handler to handle results from calls to firebase使用完成处理程序来处理调用 firebase 的结果
【发布时间】:2017-02-15 23:12:07
【问题描述】:

我正在尝试实现一个完成处理程序来处理我调用 firebase 返回的结果。到目前为止,当我调用该函数时,它会直接跳转到completionHandler(result!) 并返回 nil。我做错了什么?

//View Controller

FireChangePassword(email: (User.current?.email)!, currentPassword: currentPassword!, newPassword: newPassword!, completionHandler: { (result) -> Void in

    if result == ChangePasswordResult.AuthError{
        errorLabel.text = "Incorrect Passworld"
    }
    else if result == ChangePasswordResult.FBError{
        errorLabel.text = "System Error"
    } 
    else if result == ChangePasswordResult.Success{
        _ = self.navigationController?.popToRootViewController(animated: true)
     }
})

//Firebase.swift

enum FirebaseErrors:Error {
        case AuthError
        case FBError
        case Success   
}

typealias CompletionHandler = (_ result:ChangePasswordResult) -> Void

func FireChangePassword(email: String, currentPassword: String, newPassword: String, completionHandler: CompletionHandler) {

    let user = FIRAuth.auth()?.currentUser
    let credential = FIREmailPasswordAuthProvider.credential(withEmail: email, password: currentPassword)
    var result : ChangePasswordResult?


    user?.reauthenticate(with: credential) { error in
        if let error = error {
            // An error happened.
            print("Firebase ReAuthentication Error")
            print(error)

            result = ChangePasswordResult.AuthError

        } else {
            // User re-authenticated.
            FIRAuth.auth()?.currentUser?.updatePassword(newPassword) { (error) in
                if error == nil {
                    print("Firebase Change Password Successful")
                    result = ChangePasswordResult.Success

                }
                else {
                    print(error!)
                    print("Firebase Change Password Failed")
                    result = ChangePasswordResult.FBError
                }

            }
        }
    }

    completionHandler(result!)

}

【问题讨论】:

  • 你为什么要这样做?处理闭包内的错误(这是它的设计方式)。如果有错误返回之前的 viewController 并通知用户,如果没有错误,则继续。试图通过 throws 处理它会导致各种异步问题..
  • 我不确定我知道该怎么做。我正在尝试从FireChangePassword 返回一些东西,所以我知道是否有错误或请求是否成功。但是对 firebase 的调用是异步的,并且函数会在 firebase 返回结果之前继续前进,所以我的FireChangePassword 最终返回了一个 nil 值。
  • 没错。 Firebase 是异步的,并非旨在返回值 - 返回实际上是用于同步方法。当 Firebase 数据有效时,它将在 Firebase 函数调用之后的闭包内。从那里您可以确定密码是否已成功更改。如果不是,只需返回 viewController 并通知用户,如果是,则继续前进到下一个控制器。在封闭件内完成所有这些操作,其余的将就位。
  • 对不起,我仍然没有看到如何实施您的解决方案。我的问题是我创建了一个单独的 swift 文件来处理我所有的 firebase 调用。我无法从 firebase 闭包中弹出视图控制器,因为它没有在视图控制器中定义。所以我认为我必须自定义 firebase 调用以使用完成处理程序来让我知道是否有错误或请求是否成功。
  • 你会想要改变你的策略,因为 Firebase 中的一切都是异步的,并且期望返回值会有问题。将 Firebase 调用作为应用流程的一部分实现...用户输入新密码并点击更改,调用 Firebase 函数来更改密码。如果成功则在内部关闭,然后移动到下一个 viewController。如果不在同一个 viewController 上并显示错误消息。尝试实现完成处理程序将导致相同的问题,因为在调用结果发生关闭之前,您绝对不能在 UI 中继续前进。

标签: ios firebase swift3 firebase-authentication


【解决方案1】:

这是一个简化的更改密码过程。

假设用户正在查看带有密码文本字段的 viewController,用户可以在其中输入更新的密码。

他们输入新密码并点击“更改”按钮 - 然后该按钮调用此代码:

class ViewController: UIViewController {

  @IBAction func buttonAction(_ sender: Any) {

      let user = FIRAuth.auth()?.currentUser
      let updatedPassword = self.passwordField.text
      user?.updatePassword(updatedPassword, completion: {  error in
         if error != nil {
           print("Error. Show error in current viewController")
         } else {
           print("Login Successful, go to next viewController")
         }
      })
   }

【讨论】:

  • 明白了。我一直认为应该将尽可能多的代码移出视图控制器。为我的所有 firebase 调用创建一个单独的 swift 文件是有意义的。
  • @Brosef ViewController 就是这样 - 视图的控制器。它负责该视图中发生的所有事情 - 按钮点击或单击、处理、处理 segue、错误消息等。让 viewController 完成它的工作,让 Firebase 为您完成繁重的工作。在闭包中处理 Firebase 数据并在您的 UI 中移动,让 Firebase 设定节奏。听上去,您已经为 Firebase 调用设置了单例模式——在这种情况下,这可能不是必需的。如果我的回答有帮助,请接受它,以便其他人知道如何处理相同的用例。
猜你喜欢
  • 2018-10-23
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-18
  • 1970-01-01
相关资源
最近更新 更多