我試圖實現完成處理程序來處理從我對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並通知用戶,如果沒有錯誤,則繼續。試圖通過拋出來處理它會導致各種異步問題。 – Jay
我不知道我知道如何做到這一點。我試圖從'FireChangePassword'返回一些東西,所以我知道是否有錯誤或請求是否成功。但是對firebase的調用是異步的,並且在firebase返回結果之前函數繼續前進,所以我的「FireChangePassword」最終返回一個零值。 – Brosef
這是正確的。 Firebase是異步的,並不旨在返回值 - 返回值實際上是同步方法。當Firebase數據有效時,它將位於Firebase函數調用後的關閉內。從那裏您可以確定密碼是否已成功更改。如果不是,只需返回viewController並通知用戶,如果是這樣,則繼續前進到下一個控制器。把所有這些都放在封閉物裏面,其餘的都會落到位。 – Jay