背景
非同期で幾つか処理をしている状態で、値の取得が完了したら後続処理を行いたい場合がありました。
セマフォで後続処理を行わないようにしていましたが、記述箇所が増えてしまい、
見通しが悪くなってきたので、待機条件と後続処理をBlockで記述できるようにExtensionを書きました。
コード
/// 条件をクリアするまで待ちます
///
/// - Parameters:
///   - waitContinuation: 待機条件
///   - compleation: 通過後の処理
func wait(_ waitContinuation: @escaping (()->Bool), compleation: @escaping (()->Void)) {
    var wait = waitContinuation()
    // 0.01秒周期で待機条件をクリアするまで待ちます。
    let semaphore = DispatchSemaphore(value: 0)
    DispatchQueue.global().async {
        while wait {
            DispatchQueue.main.async {
                wait = waitContinuation()
                semaphore.signal()
            }
            semaphore.wait()
            Thread.sleep(forTimeInterval: 0.01)
        }
        // 待機条件をクリアしたので通過後の処理を行います。
        DispatchQueue.main.async {
            compleation()
        }
    }
}
使い方
var imgData: NSData! = nil
DispatchQueue.global().async {
    imgData = NSData(contentsOf: URL(string: "http://hogehoge.com/fugafuga.png")!)
}
// dataを取得するまで待ちます
wait( { return imgData == nil } ) {
	// 取得しました
    print("finish")
    UIImage(data: imgData as Data)
}