关于 DispatchSourceTimer 的使用

在网上找到的一个比较好的封装, 自己再进行了一些处理, 保证启动和停止是线程安全的.

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")
    }
}

用法:

  1. 创建并持有 timer(如果没有被其他对象持有, 则会被释放掉)
  2. 要开始计时, 调用 timer 的 resume 方法.
  3. 要停止计时, 调用 timer 的 suspend 方法.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容