// 优点: 1.不用考虑RunLoop,切换RunLoop的时候 定时器照样跑
// 2.不用考虑强引用导致 控制器不销毁的问题,定时器的生命周期和和其所在生命范围一致,在方法里面那就方法执行完毕即停止,在控制器里面则在控制器销毁时候停止。
// 3.多次创建没问题,一个指针只会指向一个实例。当这个实例不被指向的时候就销毁不再执行
import UIKit
class DZTimer {
/// GCD 定时器
var codeTimer : DispatchSourceTimer!
/// 定时器初始化 定时器立即开始一次
///
/// - Parameters:
/// - seconds: 多长时间执行一次
/// - timeout: 设置不设置超时时间 默认永远不超时
/// - timerAction: 回掉
init(seconds:Double,timeout:Double = Double(CGFloat.greatestFiniteMagnitude),timerAction:@escaping ()->()) {
// 在global线程里创建一个时间源
var timeout = timeout
codeTimer = DispatchSource.makeTimerSource(queue:DispatchQueue.global())
// 设定这个时间源是seconds设定的秒循环一次,立即开始 设置1000 的原因是毫秒计时
codeTimer.scheduleRepeating(deadline: .now(), interval: .milliseconds(Int(seconds * 1000)))
// 设定时间源的触发事件
codeTimer.setEventHandler(handler: { [weak self] _ in
// 每半秒计时一次
timeout = timeout - 1
// 时间到了取消时间源
if timeout <= 0{
self?.codeTimer.cancel()
}
// 返回主线程处理一些事件,更新UI等等
DispatchQueue.main.async {
timerAction()
}
})
//启动定时器
if #available(iOS 10.0, *) {
codeTimer.activate()
} else {
codeTimer.resume()
// Fallback on earlier versions
}
}
/// 终止定时器
func cancel() {
codeTimer.cancel()
}
}