Swift

[Swift] AlamofireでSemaphoreを使って同期通信する

More than 1 year has passed since last update.

whileで終わるまでループってまじかよ ―「先人」の嘆き

忙しい人向け

これで解決:star:

let semaphore = DispatchSemaphore(value: 0)
let queue     = DispatchQueue.global(qos: .utility)
Alamofire.request("https://qiita.com").response(queue: queue) { response in
    ???
    semaphore.signal()
}
semaphore.wait()

Alamofireを同期通信しようとするとデッドロックが起きる

Alamofireでデータ受信が終わるまで待機する方法 - Qiita
Alamofire(非同期通信)をsemaphoreで同期的に処理できなかった
などにあるように、セマフォでAlamofireの通信終了を待とうとするとデッドロックが発生します。

let semaphore = DispatchSemaphore(value: 0)
Alamofire.request("https://qiita.com").response{ response in
    ???
    semaphore.signal()
}
semaphore.wait()

これは、responsecompletionHandler({}の部分)がDispatchQueue.mainで実行されるため、同じくDispatchQueue.mainsemaphore.wait()を行うとcompletionHandlerの実行までも止まってしまいデッドロックが発生してしまう、という寸法です。

解決策

completionHandlerDispatchQueue.main以外で実行させれば良いので、 responseの引数に実行させたいqueueを指定してやれば良いです。

余談

逆にAlamofireの処理はDispatchQueue.mainのままにしておきDispatchQueue.global()semaphore.wait()を呼ぶことでも解決できますが、面倒な上に何やってるか把握しづらいのでやめたほうがいいと思います。

参考ページ

Alamofireでデータ受信が終わるまで待機する方法 - Qiita
Alamofire(非同期通信)をsemaphoreで同期的に処理できなかった
GCD のディスパッチセマフォを活用する (Objective-C〜Swift 3 対応)