1. ホーム
  2. swift

[解決済み] 非同期ネットワークリクエストのswift forループの実行が終了するまで待つ

2022-04-24 11:47:14

質問

for inループでfirebaseに大量のネットワークリクエストを送信し、メソッドの実行が終了したら新しいビューコントローラにデータを渡したいのです。以下は私のコードです。

var datesArray = [String: AnyObject]()

for key in locationsArray {       
    let ref = Firebase(url: "http://myfirebase.com/" + "\(key.0)")
    ref.observeSingleEventOfType(.Value, withBlock: { snapshot in

        datesArray["\(key.0)"] = snapshot.value
    })
}
// Segue to new view controller here and pass datesArray once it is complete 

いくつか気になる点があります。まず、forループが終了して、すべてのネットワークリクエストが完了するまで、どのように待てばいいのでしょうか?私はobserveSingleEventOfType関数を修正することができません、それはfirebase SDKの一部です。また、forループの異なる反復からdatesArrayにアクセスしようとすることで、ある種のレースコンディションを作成するのでしょうか(それが意味をなすことを願っています)?私はGCDとNSOperationについて読んできましたが、これは私が作った最初のアプリなので、私は少し迷っています。

注:Locations配列は、私がfirebaseでアクセスする必要があるキーを含む配列です。また、ネットワークリクエストは非同期で実行されることが重要です。私は、datesArrayを次のビューコントローラに渡す前に、すべての非同期リクエストが完了するまで待ちたいのです。

解決方法は?

を使用することができます。 ディスパッチグループ を使用すると、すべてのリクエストの終了時に非同期コールバックを起動することができます。

以下は、ディスパッチグループを使って、複数のネットワーキング・リクエストがすべて終了したときに、非同期にコールバックを実行する例です。

override func viewDidLoad() {
    super.viewDidLoad()

    let myGroup = DispatchGroup()

    for i in 0 ..< 5 {
        myGroup.enter()

        Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { response in
            print("Finished request \(i)")
            myGroup.leave()
        }
    }

    myGroup.notify(queue: .main) {
        print("Finished all requests.")
    }
}

出力

Finished request 1
Finished request 0
Finished request 2
Finished request 3
Finished request 4
Finished all requests.