2017-02-15 2 views
0

私は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!) 

} 
+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呼び出しのための別々の迅速なファイルを持つことが理にかなった。 – Brosef

+0

@Brosef ViewControllerは、ビューのコントローラです。そのビュー内で発生するすべてのこと(ボタンのタップやクリック、処理、セグ、エラーメッセージなど)を担当します。viewControllerにその仕事をさせ、Firebaseにあなたのために重労働をさせます。 Firebaseのデータをクロージャ内で処理し、UIを通って移動し、Firebaseがペースを設定できるようにします。そのサウンドによって、Firebaseコール用のシングルトンパターンを設定しました。この場合はおそらく必要ありません。私の答えが助けられたら、それを受け入れて、他の人が同じユースケースをどう扱うかを知ってください。 – Jay

関連する問題