//? 優(yōu)點(diǎn): 1.不用考慮RunLoop,切換RunLoop的時(shí)候 定時(shí)器照樣跑
//? ? ? ? 2.不用考慮強(qiáng)引用導(dǎo)致 控制器不銷毀的問(wèn)題,定時(shí)器的生命周期和和其所在生命范圍一致,在方法里面那就方法執(zhí)行完畢即停止,在控制器里面則在控制器銷毀時(shí)候停止。
//? ? ? ? 3.多次創(chuàng)建沒(méi)問(wèn)題,一個(gè)指針只會(huì)指向一個(gè)實(shí)例。當(dāng)這個(gè)實(shí)例不被指向的時(shí)候就銷毀不再執(zhí)行
import UIKit
class DZTimer {
/// GCD 定時(shí)器
var codeTimer : DispatchSourceTimer!
/// 定時(shí)器初始化 定時(shí)器立即開(kāi)始一次
///
/// - Parameters:
///? - seconds: 多長(zhǎng)時(shí)間執(zhí)行一次
///? - timeout: 設(shè)置不設(shè)置超時(shí)時(shí)間 默認(rèn)永遠(yuǎn)不超時(shí)
///? - timerAction: 回掉
init(seconds:Double,timeout:Double = Double(CGFloat.greatestFiniteMagnitude),timerAction:@escaping ()->()) {
// 在global線程里創(chuàng)建一個(gè)時(shí)間源
var timeout = timeout
codeTimer = DispatchSource.makeTimerSource(queue:DispatchQueue.global())
// 設(shè)定這個(gè)時(shí)間源是seconds設(shè)定的秒循環(huán)一次,立即開(kāi)始 設(shè)置1000 的原因是毫秒計(jì)時(shí)
codeTimer.scheduleRepeating(deadline: .now(), interval: .milliseconds(Int(seconds * 1000)))
// 設(shè)定時(shí)間源的觸發(fā)事件
codeTimer.setEventHandler(handler: { [weak self] _ in
// 每半秒計(jì)時(shí)一次
timeout = timeout - 1
// 時(shí)間到了取消時(shí)間源
if timeout <= 0{
self?.codeTimer.cancel()
}
// 返回主線程處理一些事件,更新UI等等
DispatchQueue.main.async {
timerAction()
}
})
//啟動(dòng)定時(shí)器
if #available(iOS 10.0, *) {
codeTimer.activate()
} else {
codeTimer.resume()
// Fallback on earlier versions
}
}
/// 終止定時(shí)器
func cancel() {
codeTimer.cancel()
}
}