这里介绍一种更加轻量级的 Timer 实现, 适用于各种需要 Timer 的场景.
DispatchTimer 的使用
在这里封装一个用于后台线程中的计时器,如下所示:
swift
public protocol BackgroundTimer { func resume() func suspend() } public class BackgroundTimerMaker { public static func makeTimer(adding: TimeInterval, task: (()->())?) -> BackgroundTimer { return BackgroundTimerImp(deadline: .now() + adding, repeating: .never, task: task) } public static func makeTimer(adding: TimeInterval, repeatInterval: Int, task: (()->())?) -> BackgroundTimer { return BackgroundTimerImp(deadline: .now() + adding, repeating: .seconds(repeatInterval), task: task) } public static func makeTimer(repeatInterval: Int, task: (()->())?) -> BackgroundTimer { return BackgroundTimerImp(deadline: .now(), repeating: .seconds(repeatInterval), task: task) } } class BackgroundTimerImp: BackgroundTimer { private var task: (()->())? private let _timer: DispatchSourceTimer private let _lock = NSLock() private enum State { case suspended case resumed } private var state: State = .suspended init(deadline: DispatchTime, repeating: DispatchTimeInterval = .never, leeway: DispatchTimeInterval = .milliseconds(100), task: (()->())?) { self.task = task _timer = DispatchSource.makeTimerSource() _timer.schedule(deadline: deadline, repeating: repeating, leeway: leeway) _timer.setEventHandler(handler: { task?() }) } func resume() { guard state != .resumed else { return } _lock.lock() guard state != .resumed else { return } state = .resumed _timer.resume() defer { _lock.unlock() } } func suspend() { guard state != .suspended else { return } _lock.lock() guard state != .suspended else { return } state = .suspended _timer.suspend() defer { _lock.unlock() } } deinit { // 注意: 这里必须这样写, 否则在释放 timer 的时候会发生崩溃 _timer.setEventHandler {} _timer.cancel() resume() task = nil } }