2017-05-18 13 views
1

私はgroupchatID(String)を受け取り、そのグループチャットの受信者([String])のリストを返す関数を書いています。私はしかし、関数の非同期部分で苦労しています。関数を実行すると、私は探していたユーザー名の配列をコンソールに正しく表示します。関数を呼び出して、返された値を出力しようとすると、ファイヤーベース呼び出しが完了する前に配列が返されるため、常に空の配列になります。私はコールバックを使用しようとしていますが、私はすべての構文を理解していません。一度見て、何を変更する必要があるか教えてください。非同期firebase呼び出しから値を返すSwift関数

機能:

私は関数を呼び出す方法
func GetRecipientsFor(GroupChatID :String , completion: @escaping ([String]) ->()) { 
var returnArray: [String] = [""] 
rootRef.child("chatMembers").child(GroupChatID).observeSingleEvent(of: .value, with: { (snapshot) in 
    for child in snapshot.children.allObjects { 
     var append = child as! FIRDataSnapshot 
     returnArray.append((append.key as String)) 
     print("Return Array Currently Contains: \(returnArray)") 
     //The above printout works properly and when the for loop finishes, the array is exactly as I want it 
    } 
    completion(returnArray) 
    //BUT, this portion returns an empty array 
}) 
} 

GetRecipientsFor(GroupChatID: gchatID) { (result) ->() in 
     print(result) 
    } 

NEW関数呼び出し

var recipients : [String] = [""] 
DispatchQueue.main.async { 
    GetRecipientsFor(GroupChatID: gchatID) { result in 
    print(result) //PRINTS CORRECTLY!!! 
    recipients = result 
    } 
} 
print(recipients) //PRINTS A BLANK ARRAY 
+0

public func setDataForRecipe (arrayIngredients: [String]){ //whatever you want. example: self.data = arrayIngredients self.tableView.reloadData() } 
'GetRecipientsFor(GroupChatID:gchatID){(結果) - >()' GetRecipientsFor(GroupChatID:gchatID)にin' {in'がうまくいくかもしれない結果?配列を出力すると 'completion(returnArray)'の後の行は正しく出力されますか? –

+0

はい、 '完了(returnArray)'の前後に印刷を追加してください。他にも欠けているものがいくつかあります。これはそのまま動作するはずです。 –

+0

'var returnArray:[String] = [" "]'をクロージャの内側に置いてみましたか? – skwashua

答えて

1

var recipients : [String] = [""] 
DispatchQueue.main.async { 
    GetRecipientsFor(GroupChatID: gchatID) { result in 
    print(result) 
    recipients = result 
    } 
} 
print(recipients) // Completes before recipients = result 
に関する問題

は、非同期呼び出しの前に最後の行が起きていることです。

さらに説明すると、print(recipients)recipients = resultの前に発生します。受信者を使用するすべてのロジックは、その完了ブロック内で発生する必要があります。あなたが完了すなわちhandleResults(result)内の関数を呼び出すことができます含まれ、さらにロジックを持たせたい場合は、やらなければならないことは、

func getRecipients(completion: @escaping ([String]) ->()) { 
    var recipients : [String] = [""] 
    DispatchQueue.main.async { 
     GetRecipientsFor(GroupChatID: gchatID) { result in 
     print(result) 
     completion(result) 
     } 
    } 
} 

です。私はclosures/completion blocks/and async callsについてもっと読むことが非常に有益だと思います。

+0

それでは、 'recipients = result'行の後になるまで 'print(recipients)'行をどのように遅らせることができますか? –

+1

@KylePapili私は自分のレスポンスを更新しました。 –

+0

あなたが提案していることを理解しています。現在、私は完成のファンクションを持っていません。私はそれを現在の関数にどのように追加しますか? –

0

また、これを簡略化し、このようなあなたの関数に他のparamを追加firebaseオブザーバ非同期タスクを使用することができます:あなたは

func GetRecipientsFor(GroupChatID :String , controller: UIViewController){ 
    rootRef.observeSingleEvent(of: .value) { (snapshot) in 
      //here you haver your snapshot. do the stuff and 
      controller.setDataForRecipe(dataFromYourSnapshot) 
     } 
} 

そして、あなたに結果を得るために必要な場所

//コントローラがありますコントローラ:

関連する問題