2017-02-15 72 views
0

我试图实现完成处理程序来处理从我对Firebase的调用返回的结果。截至目前,当我调用函数时,它直接跳转到completionHandler(result!)并返回nil。我究竟做错了什么?使用完成处理程序处理来自Firebase调用的结果

//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!) 

} 
+0

你为什么要这么做?处理闭包内的错误(这是它的设计原理)。如果有错误返回到先前的viewController并通知用户,如果没有错误,则继续。试图通过抛出来处理它会导致各种异步问题。 – Jay

+0

我不知道我知道如何做到这一点。我试图从'FireChangePassword'返回一些东西,所以我知道是否有错误或请求是否成功。但是对firebase的调用是异步的,并且在firebase返回结果之前函数继续前进,所以我的“FireChangePassword”最终返回一个零值。 – Brosef

+0

这是正确的。 Firebase是异步的,并不旨在返回值 - 返回值实际上是同步方法。当Firebase数据有效时,它将位于Firebase函数调用后的关闭内。从那里您可以确定密码是否已成功更改。如果不是,只需返回viewController并通知用户,如果是这样,则继续前进到下一个控制器。把所有这些都放在封闭物里面,其余的都会落到位。 – Jay

回答

0

这里有一个简单的更改密码的过程。

假设用户正在查看具有密码文本字段的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") 
     } 
     }) 
    } 
+0

Gotcha。我总是觉得你应该尽可能多地从你的视图控制器中移出代码。为我的所有Firebase通话分配一个swift文件是有道理的。 – Brosef

+0

@Brosef一个ViewController就是这样 - 一个视图的控制器。它负责在该视图中发生的所有事情 - 按钮点击或点击,处理,处理segues,错误消息等。让viewController执行它的工作,让Firebase为您完成繁重的工作。在关闭过程中处理Firebase数据,并通过您的用户界面移动,让Firebase设置节奏。通过它的声音,您已经为Firebase调用设置了Singleton模式 - 在这种情况下可能不需要。如果我的回答有帮助,请接受它,以便其他人知道如何处理相同的用例。 – Jay