RXSwift(三)-Timer

Timer的几种实现方式

    1. CADisplayLink实现方式
 let cadTimer = CADisplayLink(target: self, selector: #selector(timerFire))
 cadTimer?.preferredFramesPerSecond = 1
 cadTimer?.add(to: RunLoop.current, forMode: .default)
    1. 系统Timer
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)

    1. GCDTimer
let gcdTimer = DispatchSource.makeTimerSource()
gcdTimer?.schedule(deadline: DispatchTime.now(), repeating: DispatchTimeInterval.seconds(1))
gcdTimer?.setEventHandler(handler: {
   print("hello GCD")
})
gcdTimer?.resume()

CADisplayLinkTimer准确性都依赖于Runloop,而GCDTimer不依赖于RunLoop,而且准确性更高

    1. RXTimer
let timer1 = Observable.timer(1, period: 1, scheduler: MainScheduler.instance)
timer1.subscribe { (num) in
    print("num:\(num)")
} .disposed(by: disposeBag)
  • dueTime:从现在到初始化第一次的触发定时器的时间
  • period:初始化之后每次触发的时间间隔

RXSwift中的timer,不受RunLoop影响,这里做一个大胆的猜想,他是对GCDTimer的一种封装,来探究下他的源码

public static func timer(_ dueTime: RxTimeInterval, period: RxTimeInterval? = nil, scheduler: SchedulerType)
        -> Observable {
        return Timer(
            dueTime: dueTime,
            period: period,
            scheduler: scheduler
        )
    }

返回的是一个Observable序列

final private class Timer: Producer {
    fileprivate let _scheduler: SchedulerType
    fileprivate let _dueTime: RxTimeInterval
    fileprivate let _period: RxTimeInterval?

    init(dueTime: RxTimeInterval, period: RxTimeInterval?, scheduler: SchedulerType) {
        self._scheduler = scheduler
        self._dueTime = dueTime
        self._period = period
    }

    override func run(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        if self._period != nil {
            let sink = TimerSink(parent: self, observer: observer, cancel: cancel)
            let subscription = sink.run()
            return (sink: sink, subscription: subscription)
        }
        else {
            let sink = TimerOneOffSink(parent: self, observer: observer, cancel: cancel)
            let subscription = sink.run()
            return (sink: sink, subscription: subscription)
        }
    }
}

Producer,run (),sink.run,跟上篇探究的核心流程有点像啊

  • Timer保存外界闭包,继承自Producer

订阅流程跟之前的一模一样,
生成一个订阅者 -----> 将订阅者传入Producer中 --------> 调用Producerrun()方法 -----> TimerSink的初始化方法 --------> sink.run()

final private class TimerSink : Sink where Observer.Element : RxAbstractInteger  {
    typealias Parent = Timer

    private let _parent: Parent
    private let _lock = RecursiveLock()

    init(parent: Parent, observer: Observer, cancel: Cancelable) {
        self._parent = parent
        super.init(observer: observer, cancel: cancel)
    }

    func run() -> Disposable {
        return self._parent._scheduler.schedulePeriodic(0 as Observer.Element, startAfter: self._parent._dueTime, period: self._parent._period!) { state in
            self._lock.lock(); defer { self._lock.unlock() }
            self.forwardOn(.next(state))
            return state &+ 1
        }
    }
}

run方法中调用了_scheduler.schedulePeriodic (),然后来看下_scheduler.schedulePeriodic的实现

public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable {
        return self._mainScheduler.schedulePeriodic(state, startAfter: startAfter, period: period, action: action)
    }

这里的action就是我们外界的闭包

 { state in
            self._lock.lock(); defer { self._lock.unlock() }
            self.forwardOn(.next(state))
            return state &+ 1
        }
func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable {
        let initial = DispatchTime.now() + startAfter

        var timerState = state

        let timer = DispatchSource.makeTimerSource(queue: self.queue)
        timer.schedule(deadline: initial, repeating: period, leeway: self.leeway)
        
        // TODO:
        // This looks horrible, and yes, it is.
        // It looks like Apple has made a conceputal change here, and I'm unsure why.
        // Need more info on this.
        // It looks like just setting timer to fire and not holding a reference to it
        // until deadline causes timer cancellation.
        var timerReference: DispatchSourceTimer? = timer
        let cancelTimer = Disposables.create {
            timerReference?.cancel()
            timerReference = nil
        }

        timer.setEventHandler(handler: {
            if cancelTimer.isDisposed {
                return
            }
            timerState = action(timerState)
        })
        timer.resume()
        
        return cancelTimer
    }

点进来恍然大悟,跟我们之前的设想一摸一样,是对GCD的封装
timerState = action(timerState) 这里保证了我们外界的信号每隔一段时间就发送一次.

具体流程请参考 RXSwift(二)-工作流程

你可能感兴趣的:(RXSwift(三)-Timer)