February 15, 2017

asyncAfterをキャンセルする

Categories: 技術 | Tags: #Swift #非同期 #キャンセル


Swift3になってから、どうやってDispatchQueueの asyncAfter をキャンセルしようか考えていたのですが、
DispatchWorkItemを使えば簡単にできそうな気がしたので DispatchQueueextension として書いてみました

extension DispatchQueue {
    func cancelableAsyncAfter(deadline: DispatchTime, execute: @escaping () -> Void) -> DispatchWorkItem {
        let item = DispatchWorkItem(block: execute)
        asyncAfter(deadline: deadline, execute: item)
        return item
    }
}

使い方としてはこんな感じです↓

let item = DispatchQueue.main.cancerableAsyncAfter(deadline: .now() + 3.0) {
    print("execute!")
}

item.cancel()

実行前 であれば、DispatchWorkItemのインスタンスに対して cancel() を呼んであげると、実行させずに済みます。
ちなみに、 cancel() を呼び出すまでは、実際に asyncAfter で呼び出されても、呼び出す前でも、手動で perform() を呼び出せば
実行することができます。

let item = DispatchQueue.main.cancerableAsyncAfter(deadline: .now() + 3.0) {
    print("execute!")
}

DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    item.performe() // 実行される
    item.cancel()
    item.performe() // 実行されなくなる (item.isCancelledがtrueになる)    
}
// ========== (実行結果)
"execute!"
"execute!"

ひとまずはこれで良さそう。


written by sgr-ksmt