在网上找到的一个比较好的封装, 自己再进行了一些处理, 保证启动和停止是线程安全的.
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()
defer {
_lock.unlock()
}
guard state != .resumed else { return }
state = .resumed
_timer.resume()
}
func suspend() {
guard state != .suspended else { return }
_lock.lock()
defer {
_lock.unlock()
}
guard state != .suspended else { return }
state = .suspended
_timer.suspend()
}
deinit {
_timer.setEventHandler {}
task = nil
print("deinit timer source")
}
}
用法:
- 创建并持有 timer(如果没有被其他对象持有, 则会被释放掉)
- 要开始计时, 调用 timer 的 resume 方法.
- 要停止计时, 调用 timer 的 suspend 方法.