定时器有很多种实现方式,我们经常使用的定时器就是Timer了,然而 Timer 是基于线程的Runloop的,当执行单词操作时,定时器执行完毕就会销毁,并从 runloop 中弹出。当执行多次时,就需要手动调用invalidate进行销毁,并从当前 runloop 中弹出。
如果定时器没有加入 runloop 或者当前的 runloop 不是 Timer 加入的 runloop,则会造成 Timer 不能按我们的预期执行。
GCD生成的定时器则不受 runloop 的影响
// 使用 GCD 创建定时器:
let timer = DispatchSource.MakeTimerSource()
// 配置定时器参数
// deadline: 何时启动,类型为 DispatchTime ,这个时间精度可以达到纳秒级,DispatchTime.now() 可以获取当前时间,使用 + 号可以加时间, DispatchTimeInterval.seconds(1),生成秒的时间
// repeating:多久重复一次,类型为 DispatchTimeInterval
// leeway 时间容差,是一个定时时间的宽容度,具有一个默认值,所以调用此方法的时候可以不用指定这个参数,如果要指定的话,也是 DispatchTimeInterval 类型
timer.schedule(deadline:repeating:leeway:)
// 设置定时器任务处理
timer.setEventHandler(handler: (() -> Void)?)
// 设置定时器取消时的处理
timer.setCancelHandle(handler: (() -> Void)?)
// 开启运行或恢复运行
timer.resume()// suspend() 挂起定时器,可以使用 resumne() 恢复运行
// 取消定时器
timer.cancel()
// 示例:
class TimerDemo {
private var timeCount = 5
private var gcdTimer: DispatchSourceTimer?
static let share = TimerDemo()
func run() {
print("TimerDemo")
}
func oneshot() {
gcdTimer = DispatchSource.makeTimerSource()
gcdTimer?.setEventHandler(handler: {
print("\(Date()):倒计时结束!")
})
gcdTimer?.schedule(deadline: .now() + .seconds(1))
gcdTimer?.resume()
}
func loop() {
gcdTimer = DispatchSource.makeTimerSource()
gcdTimer?.setEventHandler(handler: {
if self.timeCount <= 0 {
self.gcdTimer?.cancel()
return
}
self.timeCount -= 1
print("\(Date()):倒计时\(self.timeCount)秒")
})
gcdTimer?.setCancelHandler(handler: {
print("\(Date()):倒计时结束!")
})
gcdTimer?.schedule(deadline: .now() + .seconds(1), repeating: .seconds(1))
gcdTimer?.resume()
}
}
//TimerDemo.share.run()
//TimerDemo.share.oneshot()
TimerDemo.share.loop()