延时执行
代码块的延时运行我们很常见也很常用,不少封装都不错也易于使用。在GCD的基础上我们可以将代码延时运行封装得更好用一些,再加上可以取消延时的功能,我们通过捕获一个cancel标识变量来实现delay call的取消,下面是完整的封装方法,可以尝试调用看看~
typealias Task = (_ cancel: Bool) -> Void
/// 代码延迟运行
///
/// - Parameters:
/// - delayTime: 延时时间。比如:.seconds(5)、.milliseconds(500)
/// - qosClass: 要使用的全局QOS类(默认为 nil,表示主线程)
/// - task: 延迟运行的代码
/// - Returns: Task?
@discardableResult
static func bk_delay(by delayTime: TimeInterval, qosClass: DispatchQoS.QoSClass? = nil, _ task: @escaping () -> Void) -> Task? {
func dispatch_later(block: @escaping () -> Void) {
let dispatchQueue = qosClass != nil ? DispatchQueue.global(qos: qosClass!) : .main
dispatchQueue.asyncAfter(deadline: .now() + delayTime, execute: block)
}
var closure: (() -> Void)? = task
var result: Task?
let delayedClosure: Task = { cancel in
if let internalClosure = closure {
if !cancel {
DispatchQueue.main.async(execute: internalClosure)
}
}
closure = nil
result = nil
}
result = delayedClosure
dispatch_later {
if let delayedClosure = result {
delayedClosure(false)
}
}
return result
}
/// 取消代码延时运行
func delayCancel(_ task: Task?) {
task?(true)
}
使用的时候就很简单啦~如下调用:
delay(by: 3) { print("3秒后执行") }
想要取消的话,我们可以先保留一个对Task的引用,然后调用delayCancel:
let task = delay(by: 2) { print("2秒后执行") }
// 不执行了,还是取消掉吧
delayCancel(task)
倒计时
这里分享的也是GCD的倒计时封装,比起Timer项目中要根据自身情况合理使用不同计时方法。
/// GCD定时器倒计时
///
/// - Parameters:
/// - timeInterval: 间隔时间
/// - repeatCount: 重复次数
/// - handler: 循环事件,闭包参数: 1.timer 2.剩余执行次数
func dispatchTimer(timeInterval: Double, repeatCount: Int, handler: @escaping (DispatchSourceTimer?, Int) -> Void) {
if repeatCount <= 0 {
return
}
let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
var count = repeatCount
timer.schedule(deadline: .now(), repeating: timeInterval)
timer.setEventHandler {
count -= 1
DispatchQueue.main.async {
handler(timer, count)
}
if count == 0 {
timer.cancel()
}
}
timer.resume()
}
定时器
直接上代码啦~
/// GCD实现定时器
///
/// - Parameters:
/// - timeInterval: 间隔时间
/// - handler: 事件
/// - needRepeat: 是否重复
func dispatchTimer(timeInterval: Double, handler: @escaping (DispatchSourceTimer?) -> Void, needRepeat: Bool) {
let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
timer.schedule(deadline: .now(), repeating: timeInterval)
timer.setEventHandler {
DispatchQueue.main.async {
if needRepeat {
handler(timer)
} else {
timer.cancel()
handler(nil)
}
}
}
timer.resume()
}
总之,GCD的使用方法多种多样,多多练习尝试使用~
联系方式:kim77895pl@gmail.com
Kim 写于2020.9.2,希望文章能对你有所帮助。
网友评论