2017-02-15 34 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

相關問題