enum RepeatingTimerState {
case suspended
case resumed
}
protocol PrompterTimeHelperProtocol: NSObjectProtocol {
func eventHandler(_ timer: RepeatingTimer)
func statusChange(_ status: RepeatingTimerState)
}
/// 提词器定时器逻辑 helper
class RepeatingTimer {
// MARK: - 外部属性
weak var delegate: PrompterTimeHelperProtocol?
// MARK: - 内部属性
private let timeInterval: DispatchTimeInterval
private var state: RepeatingTimerState = .suspended {
didSet {
delegate?.statusChange(state)
}
}
private lazy var timer: DispatchSourceTimer = {
let t = DispatchSource.makeTimerSource(flags: .strict, queue: DispatchQueue.global())
t.schedule(deadline: .now() + self.timeInterval, repeating: self.timeInterval)
t.setEventHandler(handler: { [weak self] in
guard let self = self else { return }
self.eventHandler()
})
return t
}()
required init(timeInterval: DispatchTimeInterval) {
self.timeInterval = timeInterval
}
deinit {
cancel()
}
}
// MARK: - About Public Custom Action
extension RepeatingTimer {
func resume() {
if state == .resumed {
return
}
state = .resumed
timer.resume()
}
func suspend() {
if state == .suspended {
return
}
state = .suspended
timer.suspend()
}
func cancel() {
timer.setEventHandler {}
timer.cancel()
/*
If the timer is suspended, calling cancel without resuming
triggers a crash. This is documented here https://forums.developer.apple.com/thread/15902
*/
resume()
delegate = nil
}
}
// MARK: - About Private Custom Action
private extension RepeatingTimer {
func eventHandler() {
DispatchQueue.main.async {
self.delegate?.eventHandler(self)
}
}
}
网友评论