一.swift中常见的几种定时器初始化方法:
1)第一种:常用定时器
let timer = Timer.init(timeInterval: 1, target: self, selector: #selector(firmTimer), userInfo: nil, repeats: true)
RunLoop.current.add(timer, forMode: .common)
@objc func firmTimer(){
print("定时器")
}
2)第二种:CADisplayLink
let CATimer: CADisplayLink = CADisplayLink(target: self, selector: #selector(firmTimer))
CATimer.preferredFramesPerSecond = 1
CATimer.add(to: .current, forMode: .common)
3)第三种:DispatchSourceTimer
var gcdTimer: DispatchSource?
self.gcdTimer = DispatchSource.makeTimerSource() as? DispatchSource
self.gcdTimer?.schedule(deadline: DispatchTime.now(), repeating: DispatchTimeInterval.seconds(1))
self.gcdTimer?.setEventHandler(handler: {
print("定时器")
})
self.gcdTimer?.resume()
⚠️GCDTimer有一点需要注意一下,因为 gcdTimer 是个局部变量,当函数执行完之后,会被自动释放,也就不会再执行handler的方法了,所以要写成全局变量。
对比三种方法:第一种和第二种会受到
Runloop的影响,第三种不会。
二.来看一下RXSwift中的定时器
let timer = Observable<Int>.interval(DispatchTimeInterval.seconds(1), scheduler: MainScheduler.instance)
timer.subscribe(onNext: { (num) in
print(num)
})
.disposed(by: disposeBag)
RXSwift 中的Timer不受Runloop的影响,让我们一起探究一下,它是如何实现的。
- 首先来看
Timer的创建
let timer = Observable<Int>.interval(DispatchTimeInterval.seconds(1), scheduler: MainScheduler.instance)
会来到Timer的Timer.swift中的interval方法中
public static func interval(_ period: RxTimeInterval, scheduler: SchedulerType) -> Observable<Element> {
return Timer(
dueTime: period,
period: period,
scheduler: scheduler
)
}
点进Timer
final private class Timer<Element: RxAbstractInteger>: Producer<Element> {
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: ObserverType>(_ 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)
}
}
}
Timer初始化时将外界传来的scheduler ,dueTime, period保存为属性。
- 再来看一下Timer的订阅
timer.subscribe(onNext: { (num) in
print(num)
})
会来到ObservableType+Extensions的 subscribe方法中
public func subscribe(onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)
-> Disposable {
let disposable: Disposable
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
#if DEBUG
let synchronizationTracker = SynchronizationTracker()
#endif
let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : []
let observer = AnonymousObserver<Element> { event in
#if DEBUG
synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { synchronizationTracker.unregister() }
#endif
switch event {
case .next(let value):
onNext?(value)
case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler(callStack, error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
}
}
初始化let observer = AnonymousObserver<Element> { event in的匿名观察者 AnonymousObserver 后面尾随闭包做参数。
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
又会带我们来到父类的Producer的Producer中 -> 会回到自己的run方法中
override func run<Observer: ObserverType>(_ 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)
}
}
接下来就会来到TimerSink中
final private class TimerSink<Observer: ObserverType> : Sink<Observer> where Observer.Element : RxAbstractInteger {
typealias Parent = Timer<Observer.Element>
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
}
}
}
看一下TimerSink 的run方法,返回一个self._parent._scheduler.schedulePeriodic我们来看一下
func schedulePeriodic<StateType>(_ 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
}
let timer = DispatchSource.makeTimerSource(queue: self.queue)在这段代码中我们可以看出来用的GCD Timer,所以才不会收到runLoop的影响,
timer.setEventHandler(handler: {
if cancelTimer.isDisposed {
return
}
timerState = action(timerState)
})
Timer会不断的执行这个EventHandler中的timerState = action(timerState),让我们来看一下这个action是什么
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
}
}
action 就是TimerSink中的run函数中的逃逸闭包啊
{ state in
self._lock.lock(); defer { self._lock.unlock() }
self.forwardOn(.next(state))
return state &+ 1
}
这里的会调用self.forwardOn(.next(state))函数,并把state带过去,
forwardOn我们熟悉的函数,之后的的流程和上一篇从创建到相应是一样的。
如何取消定时器:根据序列的特点可发送,错误,销毁,使timer停止。