前言
在使用ReactiveCocoa的时候,对于型号在主线程上的处理经常会用到observeOn(UIScheduler())
或者observeOn(QueueScheduler.main)
。从字面意思来讲UI线程和主线程应该是同一个线程,那么这两个用法有什么区别呢?
源码
要想知道内部的区别,需要从源码入手。
下面是ReactiveCocoa5.0.0-alpha.3的相关代码。
UISchdule的描述:
/// A scheduler that performs all work on the main queue, as soon as possible.
///
/// If the caller is already running on the main queue when an action is
/// scheduled, it may be run synchronously. However, ordering between actions
/// will always be preserved.
尽可能的在主队列上执行所有工作的调度器。
如果调度程序在操作时已在主队列上运行,则可以同步运行。 但是,操作之间的顺序将始终保留。
UISchdule的代码:
public final class UIScheduler: SchedulerProtocol {
private static let dispatchSpecificKey = DispatchSpecificKey<UInt8>()
private static let dispatchSpecificValue = UInt8.max
private static var __once: () = {
DispatchQueue.main.setSpecific(key: UIScheduler.dispatchSpecificKey,
value: dispatchSpecificValue)
}()
······
public init() {
/// This call is to ensure the main queue has been setup appropriately
/// for `UIScheduler`. It is only called once during the application
/// lifetime, since Swift has a `dispatch_once` like mechanism to
/// lazily initialize global variables and static variables.
_ = UIScheduler.__once
}
······
代码中可以看到,在初始化方法中调用了自己的私有的静态函数,在主线程上设置了一对键值。
而从注释可以看出,init方式是用来确保UIScheduler
已经正确设置为主线程,而且只会在应用周期里面调用一次。
QueueScheduler的描述:
A scheduler backed by a serial GCD queue.
由串行GCD支持的调度器
简单明了。
QueueScheduler.main的相关代码:
public final class QueueScheduler: DateSchedulerProtocol {
/// A singleton `QueueScheduler` that always targets the main thread's GCD
/// queue.
///
/// - note: Unlike `UIScheduler`, this scheduler supports scheduling for a
/// future date, and will always schedule asynchronously (even if
/// already running on the main thread).
public static let main = QueueScheduler(internalQueue: DispatchQueue.main)
public let queue: DispatchQueue
internal init(internalQueue: DispatchQueue) {
queue = internalQueue
}
}
简单来说,QueueScheduler.main
其实就是QueueScheduler
在主线程上的单例模式,而下面note这句话也最终解释了UIScheduler
与QueueScheduler.main
的区别的区别。
区别
UIScheduler
与QueueScheduler.main
背后都是通过GCD调用的主线程,区别是QueueScheduler.main
只能在主线程上异步执行,而调用UIScheduler
时,如果本身已经在主线程上了,那么就可以可以在主线程上同步执行,