whileで終わるまでループってまじかよ ―「先人」の嘆き
忙しい人向け
これで解決
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()
これは、response
のcompletionHandler
({}の部分)がDispatchQueue.main
で実行されるため、同じくDispatchQueue.main
でsemaphore.wait()
を行うとcompletionHandler
の実行までも止まってしまいデッドロックが発生してしまう、という寸法です。
解決策
completionHandler
をDispatchQueue.main
以外で実行させれば良いので、 response
の引数に実行させたいqueue
を指定してやれば良いです。
余談
逆にAlamofireの処理はDispatchQueue.main
のままにしておきDispatchQueue.global()
でsemaphore.wait()
を呼ぶことでも解決できますが、面倒な上に何やってるか把握しづらいのでやめたほうがいいと思います。
参考ページ
Alamofireでデータ受信が終わるまで待機する方法 - Qiita
Alamofire(非同期通信)をsemaphoreで同期的に処理できなかった
GCD のディスパッチセマフォを活用する (Objective-C〜Swift 3 対応)