前两天在写代码过程中遇到 延迟任务需要中途取消的操作,当时把我给难住了,后来在网上查一些资料,看到王魏的 《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
网友评论