前兩天在寫代碼過程中遇到 延遲任務需要中途取消的操作,當時把我給難住了,後來在網上查一些資料,看到王魏的 《Swfit Tips》中的一個實現方法,感覺很棒,稍做修改後,在此分享給大家。
延遲任務通GCD DispatchQueue.main.asyncAfter 實現, 主要思路是 把GCD中 block中的實現引用出來, 如果中途需求取消,則將block置爲空,當延遲時間到達時將不再做任何事情。
實現代碼:
class GCDTool: NSObject {
typealias GCDTask = (_ cancel: Bool) -> ()
@discardableResult static func gcdDelay(_ time: TimeInterval, task: @escaping () -> ()) -> GCDTask?{
func dispatch_later(block: @escaping () -> ()) {
let t = DispatchTime.now() + time
DispatchQueue.main.asyncAfter(deadline: t, execute: block)
}
var closure: (() -> Void)? = task
var result: GCDTask?
let delayedClosure: GCDTask = {
cancel in
if let closure = closure {
if !cancel {
DispatchQueue.main.async(execute: closure)
}
}
closure = nil
result = nil
}
result = delayedClosure
dispatch_later {
if let result = result {
result(false)
}
}
return result
}
static func gcdCancel(_ task: GCDTask?) {
task?(true)
}
}
測試代碼:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let task1 = GCDTool.gcdDelay(5) {
print("延遲任務1")
}
let task2 = GCDTool.gcdDelay(9) {
print("延遲任務2")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
GCDTool.gcdCancel(task1)
GCDTool.gcdCancel(task2)
}
}
}
打印結果:
延遲任務1
代碼 GCDToolDemo