使用完成处理程序处理来自Firebase调用的结果
我试图实现完成处理程序来处理从我对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!)
}
这里有一个简单的更改密码的过程。
假设用户正在查看具有密码文本字段的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")
}
})
}
Gotcha。我总是觉得你应该尽可能多地从你的视图控制器中移出代码。为我的所有Firebase通话分配一个swift文件是有道理的。 – Brosef
@Brosef一个ViewController就是这样 - 一个视图的控制器。它负责在该视图中发生的所有事情 - 按钮点击或点击,处理,处理segues,错误消息等。让viewController执行它的工作,让Firebase为您完成繁重的工作。在关闭过程中处理Firebase数据,并通过您的用户界面移动,让Firebase设置节奏。通过它的声音,您已经为Firebase调用设置了Singleton模式 - 在这种情况下可能不需要。如果我的回答有帮助,请接受它,以便其他人知道如何处理相同的用例。 – Jay
你为什么要这么做?处理闭包内的错误(这是它的设计原理)。如果有错误返回到先前的viewController并通知用户,如果没有错误,则继续。试图通过抛出来处理它会导致各种异步问题。 – Jay
我不知道我知道如何做到这一点。我试图从'FireChangePassword'返回一些东西,所以我知道是否有错误或请求是否成功。但是对firebase的调用是异步的,并且在firebase返回结果之前函数继续前进,所以我的“FireChangePassword”最终返回一个零值。 – Brosef
这是正确的。 Firebase是异步的,并不旨在返回值 - 返回值实际上是同步方法。当Firebase数据有效时,它将位于Firebase函数调用后的关闭内。从那里您可以确定密码是否已成功更改。如果不是,只需返回viewController并通知用户,如果是这样,则继续前进到下一个控制器。把所有这些都放在封闭物里面,其余的都会落到位。 – Jay