2017-01-11 8 views
0

FIRUserとFIRDatabaseReferenceをとるfailable初期化子を使ってクラスを作成しようとしています。 Firebaseデータベースからデータをダウンロードし、返されたものに基づいて独自の変数を設定します。そうでなければ、イニシャライザは失敗するはずです。Firebase Data Pullからクラスを初期化する

何が起こるかは、データがクロージャーでダウンロードされた後、ダウンロードが起こらなかったかのようにすべてがデフォルト値に戻ります。

私はこのサーバのチャットロジックをクラス初期化子に入れたいと思っています。どのようにしても私はこれを安全に達成することができますか?私はこれまで多くのことを試してきましたが、それを理解することはできません。

init?(from user: FIRUser, withUserReference ref: FIRDatabaseReference){ 
    let userID = user.uid 

    var init_succeeded = false 

    //These values don't matter. If the init fails 
    //It'll return an empty class. 
    //Yes this is a hack lol 

    self.incognito = false 
    self.email = "NO" 
    self.username = "NOPE" 
    self.ref = ref 
    self.fir_user = user 
    self.mute_all = false 

    //Getting the information from the database 
    ref.child(userID).observeSingleEvent(of: .value, with: { (snapshot) in 
     // Get user value 
     let value = snapshot.value as? NSDictionary 
     //Unpacking user preferences 
     self.incognito = (value?["incognito"] as? Bool)! 
     self.mute_all = (value?["mute_all"] as? Bool)! 
     self.email = (value?["email"] as? String)! 
     self.username = (value?["username"] as? String)! 
     init_succeeded = true 
    }) { (error) in 
     print("ERROR : \(error.localizedDescription)") 
    } 

    if !init_succeeded { return nil } 
} 

ありがとうございます! - キーナン

答えて

0

単純な答え:ません

あなたは、単にそれが非同期文に依存だ関数の値returnべきではありません。 init_succeededtrueに設定されている可能性が最も高いので、このメソッドは常にnilを返します。のメソッドが返されます。 Firebaseのクエリは非同期であるため、observeSingleEventを呼び出すと、関数はその文の実行が完了するのを待たずに、非同期で実行し、コードの残りの部分(この場合はreturn)に進みます。

完了の閉鎖はあなたが得ることができる最も近い(しかし、あなたのコードは正確に初期化の方法に含まれることはありません):

init(from user: FIRUser, withUserReference ref: FIRDatabaseReference, completion: @escaping (Bool) -> Void){ 
let userID = user.uid 

// default values 
self.incognito = false 
self.email = "NO" 
self.username = "NOPE" 
self.ref = ref 
self.fir_user = user 
self.mute_all = false 

//Getting the information from the database 
ref.child(userID).observeSingleEvent(of: .value, with: { (snapshot) in 
    // Get user value 
    let value = snapshot.value as? NSDictionary 
    //Unpacking user preferences 
    self.incognito = (value?["incognito"] as? Bool)! 
    self.mute_all = (value?["mute_all"] as? Bool)! 
    self.email = (value?["email"] as? String)! 
    self.username = (value?["username"] as? String)! 

    completion(true)  // true = success 
}) { (error) in 
    completion(false) // false = failed 
    print("ERROR : \(error.localizedDescription)") 
} 

} 

そして今、基本的にこの

let myObject = myClass(from: someUser, withUserReference: someRef, completion: { success in 
if success { 
    // initialization succeeded 
} 
else { 
    // initialization failed 
} 
}) 
のようにそれを使用します

私は一般的にイニシャライザのデータを取得しないことをお勧めします。おそらく、データを取得するための特別な関数を書いて、デフォルト値のみを設定してください。init()

+0

ありがとうございました!最後に、スナップショットをクラス初期化子に渡し、残りの部分を処理させました。再度、感謝します! –

関連する問題