Blog スタッフブログ

Swift システム開発

[Swift]DispatchGroupでAPIコールを並列実行

Swift

こんにちは、株式会社MIXシステム開発担当のBloomです。

早速本題のDispatchGroupでAPIコールを並列実行する手順について、

お仕事の中で得た知見を共有させていただきたいと思います。

DispatchGroupとは

DispatchGroup – Apple Developer Documentation

DispatchGroupは複数の非同期タスクの実行を集約し、そのグループの動作を同期させることのできる標準クラスです。

実際に動作を見てみましょう。

class ViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        DispatchQueue.global().async {
            let dispatchGroup = DispatchGroup()
            
            var apiResult1: Int = 0
            var apiResult2: Int = 0
            var apiResult3: Int = 0
            
            dispatchGroup.enter()
            self.api1 { response in
                apiResult1 = response
                dispatchGroup.leave()
            }
            
            dispatchGroup.enter()
            self.api2 { response in
                apiResult2 = response
                dispatchGroup.leave()
            }
            
            dispatchGroup.enter()
            self.api3 { response in
                apiResult3 = response
                dispatchGroup.leave()
            }
            
            dispatchGroup.notify(queue: .main) {
                // ここはメインスレッドです
                print("results: \(apiResult1), \(apiResult2), \(apiResult3)")
            }
        }
    }
    
    func api1(handler:@escaping (Int) -> Void) {
        DispatchQueue.global().async {
            print("api1 start!")
            sleep(1)
            print("api1 finished!")
            handler(1)
        }
    }
    func api2(handler:@escaping (Int) -> Void) {
        DispatchQueue.global().async {
            print("api2 start!")
            sleep(2)
            print("api2 finished!")
            handler(2)
        }
    }
    func api3(handler:@escaping (Int) -> Void) {
        DispatchQueue.global().async {
            print("api3 start!")
            sleep(3)
            print("api3 finished!")
            handler(3)
        }
    }
}

実行結果ログ

api3 start!
api2 start!
api1 start!
api1 finished!
api2 finished!
api3 finished!
results: 1, 2, 3

時間差で完了するAPIコールの結果を簡単にまとめられました。

このコードではdispatchGroup.enter() をAPIコールのたびに実行する必要があり、

同様にAPIの処理が終了したらdispatchQueue.leave()を必ず実行する必要があります。

そのため、API側でタイムアウト等が発生した場合に必ずキャッチしハンドラまで処理を通達させる必要があるため注意してください。

これでAPIを並列して実行することができるようになりました。良かったですね。

参考文献

DispatchGroup – Apple Developer Documentation