一、引序

  • 任何序列都可以用 Observable 描述,创建序列 -> 订阅序列 -> 信号发送 -> 信号接收:
 Observable<Any>.create { (observer) -> Disposable inobserver.onNext("信号1")return Disposables.create()}.subscribe(onNext: { (val) inprint("信号接收区:\(val)")}).disposed(by: disposeBag)
  • Observable 是通用序列的描述符,调用 .onNext,.onError,onCompleted 来发送信号,通用性强,但针对特殊需求可能会觉得繁琐,因此 RxSwift 还提供了一组特征序列,是 Observable 序列的变种,它能够更准确的描述序列,即 Single、Completable、Maybe、Driver、Signal、ControlEvent,binder 等。

二、Single

① Single 的使用

  • Single 单元素序列,信号只发送一次,响应信号或错误信号。
  • Single 是 Observable 的另外一个版本,不像 Observable 可以发出多个元素,它要么只能发出一个元素,要么产生一个 error 事件。
  • Single 发出一个元素,或一个 error 事件,不会共享附加作用。
 let singleOB = Single<Any>.create { (single) -> Disposable inprint("singleOB 是否共享")single(.success("good"))single(.error(NSError.init(domain: "com.ydw.cn",code: 10086, userInfo: nil)))return Disposables.create()}singleOB.subscribe { (reslut) inprint("订阅:\(reslut)")}.disposed(by: disposeBag)// 输出结果singleOB 是否共享订阅:success("good")
  • 说明:
    • sinngle(.success(data)) -> onSuccess 发送响应元素到成功观察者;
    • sinngle(.error(error)) -> error 发送错误元素到错误观察者。
  • 响应元素和错误元素分开处理,此时可以联想到应用中的网络请求,成功数据用来渲染,错误数则据弹出提示框。

② Single 的源码分析

  • Single 定义:定位到 Single.swift 文件,可以看到 Single 是 PrimitiveSequence 结构体类型的别名,SingleEvent 是事件枚举,有 success 和 error 两个成员变量,如下所示:
 // Sequence containing exactly 1 elementpublic enum SingleTrait { }// Represents a push style sequence containing 1 element.public typealias Single<Element> = PrimitiveSequence<SingleTrait, Element>public enum SingleEvent<Element> {// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)case success(Element)// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)case error(Swift.Error)}
  • Single 的 create 创建序列(1⃣️),如下所示:
 extension PrimitiveSequenceType where TraitType == SingleTrait {public typealias SingleObserver = (SingleEvent<ElementType>) -> Void// 此处省略部分代码......public static func create(subscribe: @escaping (@escaping SingleObserver) -> Disposable) -> Single<ElementType> {let source = Observable<ElementType>.create { observer inreturn subscribe { event inswitch event {case .success(let element):observer.on(.next(element))observer.on(.completed)case .error(let error):observer.on(.error(error))}}}       return PrimitiveSequence(raw: source)}}
  • 可以看到参数是一个带 Disposable 类型返回值的闭包,交由外部(业务层)实现,内部调用向外传入一个 SingleObserver 闭包,以上写法不太好理解,可以换一种写法:
    • 内部实现一个闭包 block,用来接收外界传入的 SingleEvent 信号,接着做进一步的信号发送;
    • 调用外部实现的闭包方法,将内部实现的闭包 block 发送出去,起连接作用;
    • 创建 PrimitiveSequence 对象并保存 Observable 序列对象 source,返回 PrimitiveSequence 对象;
 public static func create(subscribe: @escaping (@escaping SingleObserver) -> Disposable) -> Single<ElementType> {let source = Observable<ElementType>.create { observer in// 内部实现一个闭包,用来接收外界传入的SingleEvent信号,接着做进一步的信号发送let block = { (event:SingleEvent<ElementType>) -> Void inswitch event {case .success(let element):observer.on(.next(element))observer.on(.completed)case .error(let error):observer.on(.error(error))}}// 调用外部实现的闭包方法,向外部发送内部实现的闭包方法做连接作用let disposable = subscribe(block) // 返回值Disposable对象 return disposable}return PrimitiveSequence(raw: source) // 创建PrimitiveSequence对象并保存Observable序列对象}
  • 在 create 方法内部实际上实现了一个 Observable 序列,由此可见 Single 序列是对 Observable 序列的封装,Disposable 对象通过闭包交由业务层创建,Single 序列在实现上,方式方法与 Observable 保持一致。Observable 序列的信号传递流程,请参考我的博客:RxSwift之深入解析核心逻辑Observable的底层原理。
  • 订阅序列,也是在同 PrimitiveSequenceType 扩展中定义(2⃣️),如下:
 public func subscribe(onSuccess: ((ElementType) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil) -> Disposable {#if DEBUGlet callStack = Hooks.recordCallStackOnError ? Thread.callStackSymbols : []#elselet callStack = [String]()#endifreturn self.primitiveSequence.subscribe { event inswitch event {case .success(let element):onSuccess?(element)case .error(let error):if let onError = onError {onError(error)} else {Hooks.defaultErrorHandler(callStack, error)}}}}
  • 方法中先调用了 self.primitiveSequence 方法,返回了 self,方法是在遵循 PrimitiveSequenceType 协议的 PrimitiveSequence 的扩展中,为了保证协议的一致性,如下所示:
 extension PrimitiveSequence: PrimitiveSequenceType {// Additional constraintspublic typealias TraitType = Trait// Sequence element typepublic typealias ElementType = Element// Converts `self` to primitive sequence.//// - returns: Observable sequence that represents `self`.public var primitiveSequence: PrimitiveSequence<TraitType, ElementType> {return self}}
  • 接着调用另一个 subscribe 方法(3⃣️),self.primitiveSequence -> asObservable() -> subscribe,此处截断了 completed 信号的向上传递,因此 Single 序列只能收到响应信号和错误信号,如下:
 public func subscribe(_ observer: @escaping (SingleEvent<ElementType>) -> Void) -> Disposable {var stopped = falsereturn self.primitiveSequence.asObservable().subscribe { event inif stopped { return }stopped = trueswitch event {case .next(let element):observer(.success(element))case .error(let error):observer(.error(error))case .completed:rxFatalErrorInDebug("Singles can't emit a completion event")}}}
  • subscribe 方法也调用了 self.primitiveSequence 方法,接着调用 asObservable() 方法,查看代码发现此处是为了获取 source 对象,即 Observable 可观察序列。再查看 subscribe 的方法(4⃣️):
 public func subscribe(_ on: @escaping (Event<E>) -> Void)-> Disposable {let observer = AnonymousObserver { e inon(e)}return self.asObservable().subscribe(observer)}
  • 代码创建了一个观察者,当前观察者将会收到发送过来的消息,并由此通过闭包一层层传到业务层:4️⃣ -> 3️⃣ -> 2️⃣ -> 1️⃣ ->业务层;
  • 当前 self 指向的是1️⃣处创建并保存的 Observable 类型的 source 对象,因此该处 subscribe 所调用的即是 Produce 类中的 subscribe 方法,在方法内部创建了 sink 对象,来触发创建序列时实现的闭包,即代码1️⃣处所 create 后的闭包;
  • 此时就到了业务层,通过 create 内部实现的闭包 single 向内部发送消息,再有 observer 调用 on 来向观察者发送信号;
  • 信号发送不做赘述,最终会到达4️⃣处代码的观察者,此时再由闭包一层层向上传递,直到业务层的监听闭包。
  • 序列的产生,订阅,发送,接收还是由 Observable 来实现的,Single 只是对 Observable 做了封装,去除了 onCompleted 的消息监听及消息发送。

三、Completable

  • Completable 是 Observable 的另外一个版本,不像 Observable 可以发出多个元素,它要么只能产生一个 completed 事件,要么产生一个 error 事件:
    • 发出零个元素;
    • 发出一个 completed 元素,或一个 error 事件;
    • 不会共享附加作用;
  • Completable 只能产生 completed 事件和 error 事件,没有序列元素值产生。适用于只关心任务是否完成,而不需要在意任务返回值的情况,它和 Observable 有点相似。
 let completableOB = Completable.create { (completable) -> Disposable inprint("completableOB 是否共享")completable(.completed)completable(.error(NSError.init(domain: "com.ydw.cn",code: 10086, userInfo: nil)))return Disposables.create()}completableOB.subscribe { (reslut) inprint("订阅:\(reslut)")}.disposed(by: disposeBag)// 输出结果completableOB 是否共享订阅:completed
  • 在 Competable.swift 下,在 PrimitiveSequenceType 扩展中实现了序列的创建和订阅,即信号转发。Competable 的定义如下:
 // Sequence containing 0 elementspublic enum CompletableTrait { }// Represents a push style sequence containing 0 elements.public typealias Completable = PrimitiveSequence<CompletableTrait, Swift.Never>public enum CompletableEvent {// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)case error(Swift.Error)// Sequence completed successfully.case completed}
  • 同样,Completable 类也是 PrimitiveSequence 的别名,并声明一个枚举包含,error 和 completed 成员变量,限定了事件产生类型,都是对 Observable 序列的封装,和 Single 一致,只是在订阅阶段对 .next 事件做了拦截。

四、Maybe

  • Maybe 是 Observable 的另外一个版本,它介于 Single 和 Completable 之间,它要么只能发出一个元素,要么产生一个completed 事件,要么产生一个 error 事件。
    • 发出一个元素或者一个 completed 事件或者一个 error 事件;
    • 不会共享附加作用。
  • 如果可能需要发出一个元素,又可能不需要发出时,就可以使用 Maybe。
 let maybeOB = Maybe<Any>.create { (maybe) -> Disposable inprint("maybe 是否共享")maybe(.success("A"))maybe(.completed)maybe(.error(NSError.init(domain: "com.ydw.cn",code: 10086, userInfo: nil)))return Disposables.create()}maybeOB.subscribe { (reslut) inprint("订阅:\(reslut)")}.disposed(by: disposeBag)// 输出结果maybe 是否共享订阅:success("A")

五、Driver

① Driver 使用

  • Driver 是一个精心准备的特征序列,它主要是对需要在 UI 上做出响应的序列进行了封装,简化 UI 层的代码。不过如果遇到的序列具有以下特征,也可以使用它:
    • Driver 序列不会产生 error 事件;
    • 在主线程中监听(一定要在 MainScheduler 中),会向新订阅者发送上次发送过的元素,简化 UI 层的代码;
    • 共享序列。
 let result = self.textFiled.rx.text.orEmpty.asDriver() // 普通序列转化.throttle(.milliseconds(500)).flatMap {self.dealwithData(inputText: $0).asDriver(onErrorJustReturn: "检测到错误")}// 绑定到label上面result.map { "长度:\(($0 as! String).count)" }.drive(self.label.rx.text).disposed(by: disposeBag)// 绑定到button上面result.map { ($0 as! String) }.drive(self.btn.rx.title()).disposed(by: disposeBag)
  • 说明:
    • asDriver() 将序列转换为 Driver 序列;
    • map 重新组合并生成新的序列;
    • driver 将元素在主线程中绑定到 label 和 button 上。
  • 相比非 driver 下的代码实现,Driver 序列省去了线程的设置,share 数据共享设置。

② Driver 的源码分析

  • 查看 asDriver() 方法,是 ControlProperty 的扩展方法,返回了一个Driver类:
extension ControlProperty {// Converts `ControlProperty` to `Driver` trait.//// `ControlProperty` already can't fail, so no special case needs to be handled.public func asDriver() -> Driver<E> {return self.asDriver { _ -> Driver<E> in#if DEBUGrxFatalError("Somehow driver received error from a source that shouldn't fail.")#elsereturn Driver.empty()#endif}}
}
  • Driver 是 SharedSequence 的别名,用来描述不同类型的序列,最后又调用了 asDriver 方法,而该方法在 ObservableConvertibleType 的扩展中,一直追踪会发现很多类都是继承自 ObservableConvertibleType 下:
 extension ObservableConvertibleType {public func asDriver(onErrorRecover: @escaping (_ error: Swift.Error) -> Driver<E>) -> Driver<E> {let source = self.asObservable().observeOn(DriverSharingStrategy.scheduler).catchError { error inonErrorRecover(error).asObservable()}return Driver(source)}}
  • 如上,代码也设置了 observerOn 方法,来指定线程,继续深入能够发现 DriverSharingStrategy.scheduler 内部指定的就是主线程,印证了上面所说的 Driver 的执行是在主线程的,最后初始化一个 Driver 对象返回,看一下初始化过程,及对 SharedSequence 类的初始化,代码如下:
 public struct SharedSequence<S: SharingStrategyProtocol, Element> : SharedSequenceConvertibleType {public typealias E = Elementpublic typealias SharingStrategy = Slet _source: Observable<E>init(_ source: Observable<E>) {self._source = S.share(source)}}
  • 此处调用了 share 并传入了可观察序列,感觉好像在哪见过,此处猜想它是用来共享序列的,使用 lldb:po S.self 查找 share 所在位置:RxCocoa.DriverSharingStrategy,cmd + 点击进入,代码如下:
 public typealias Driver<E> = SharedSequence<DriverSharingStrategy, E>public struct DriverSharingStrategy: SharingStrategyProtocol {public static var scheduler: SchedulerType { return SharingScheduler.make() }public static func share<E>(_ source: Observable<E>) -> Observable<E> {return source.share(replay: 1, scope: .whileConnected)}}
  • 在此处传入的序列用来掉用 share,使得当前序列作为共享序列,即 driver 序列为共享序列。

六、Signal

  • Signal 和 Driver 相似,唯一的区别是,Driver 会对新观察者回放(重新发送)上一个元素,而 Signal 不会对新观察者回放上一个元素。
    • 不会产生 error 事件;
    • 一定在 MainScheduler 监听(主线程监听);
    • 会共享附加作用。
 let result = self.textFiled.rx.text.orEmpty.asSignal(onErrorJustReturn: "没有值") // 普通序列转化为signle.throttle(.milliseconds(500)).flatMap {self.dealwithData(inputText: $0).asSignal(onErrorJustReturn: "检测到错误")}// 绑定到label上面result.map { "长度:\(($0 as! String).count)" }.emit(to: self.label.rx.text).disposed(by: disposeBag)// 绑定到button上面result.map { ($0 as! String) }.emit(to: self.btn.rx.title()).disposed(by: disposeBag)
  • 说明:
    • catchErrorJustReturn(onErrorJustReturn) 保证了无错误信号;
    • observeOn(DriverSharingStrategy.scheduler) 保证了调度环境在主线程;
    • source.share(scope: .whileConnected) 序列状态共享。

七、ControlEvent

  • ControlEvent: 专门用于描述 UI 控件所产生的事件,它具有以下特征:
    • 不会产生 error 事件;
    • 一定在 MainScheduler 订阅(主线程订阅);
    • 一定在 MainScheduler 监听(主线程监听);
    • 会共享附加作用。
 let controlEventOB = button.rx.controlEvent(.touchUpInside)controlEventOB.subscribe { (reslut) inprint("订阅:\(reslut) \n \(Thread.current)")}.disposed(by: disposeBag)controlEventOB.subscribe { (reslut) inprint("订阅:\(reslut) \n \(Thread.current)")}.disposed(by: self.disposeBag)
  • 监听点击事件:
 let event : ControlEvent<Void> = button.rx.tap.asControlEvent()event.bind(onNext: {print("controllerEvent")}).disposed(by: disposeBag)
  • 监听点击事件并绑定数据到其他 UI:
 let event : ControlEvent<Void> = button.rx.tap.asControlEvent()event.map{"yahibo"}.bind(to: label1.rx.text).disposed(by: disposeBag)

八、binder

  • 不会处理错误事件;
  • 确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler);
  • 一旦产生错误事件,在调试环境下将执行 fatalError,在发布环境下将打印错误信息。
 let observer : AnyObserver<Bool> = AnyObserver { (event) inprint("observer当前线程:\(Thread.current)")switch event{case .next(let isHidden) :print("label的状态")self.label.isHidden = isHiddencase .error(let error) :print("\(error)")case .completed :print("完成")}}let binder = Binder<Bool>(self.label) { (lab, isHidden) inprint("Binder当前线程:\(Thread.current)")lab.isHidden = isHidden}let observable = Observable<Bool>.create { (ob) -> Disposable inob.onNext(true)ob.onError(NSError.init(domain: "com.ydw.cn", code: 10086, userInfo: nil))ob.onCompleted()return Disposables.create()}.observeOn(ConcurrentDispatchQueueScheduler(queue: DispatchQueue.global()))// observable.bind(to: observer).disposed(by: self.disposeBag)observable.bind(to: binder).disposed(by: self.disposeBag)
  • RxSwift 里面也封装了很多的 binder,开发使用很直接:
 extension Reactive where Base: UIButton {// Reactive wrapper for `setTitle(_:for:)`public func title(for controlState: UIControl.State = []) -> Binder<String?> {return Binder(self.base) { button, title -> Void inbutton.setTitle(title, for: controlState)}}// Reactive wrapper for `setImage(_:for:)`public func image(for controlState: UIControl.State = []) -> Binder<UIImage?> {return Binder(self.base) { button, image -> Void inbutton.setImage(image, for: controlState)}}// Reactive wrapper for `setBackgroundImage(_:for:)`public func backgroundImage(for controlState: UIControl.State = []) -> Binder<UIImage?> {return Binder(self.base) { button, image -> Void inbutton.setBackgroundImage(image, for: controlState)}}}

RxSwift之深入解析场景特征序列的使用和底层实现相关推荐

  1. RxSwift之深入解析map操作符的底层实现

    一.map 操作符的使用 map 操作符将源 Observable 的每个元素转换一遍,然后返回含有转换结果的 Observable: 现有如下示例: Observable<Int>.of ...

  2. RxSwift之深入解析dispose源码的实现原理

    一.前言 任何对象都有生命周期,有创建就要销毁.OC 中有 init 和 dealloc,swift 有 init 和 deinit,RxSwift 也不例外,有 create 和 dispose. ...

  3. iOS之深入解析objc_msgSend消息转发机制的底层原理

    一.抛砖引玉 objc_msgSend() 消息发送的过程就是 通过 SEL 查找 IMP 的过程 . objc_msgSend() 是用 汇编语言 实现的,使用汇编实现的优势是: 消息发送的过程需要 ...

  4. RxSwift之深入解析URLSession的数据请求和数据处理

    一.请求网络数据 ① 通过 rx.response 请求数据 如下所示,通过豆瓣提供的音乐频道列表接口获取数据,并将返回结果输出到控制台中: "https://www.douban.com/ ...

  5. RxSwift之深入解析Subject的使用和实现原理

    一.Subject RxSwift 的核心逻辑 Observable 不具备发送事件的能力,创建一个 Observable 的时候就要预先将要发出的数据都准备好,等到有人订阅它时再将数据通过 Even ...

  6. RxSwift之深入解析特殊序列deallocating与deallocated的源码实现

    一.引言 在 RxSwfit 中,有两个特殊序列:deallocating 与 deallocated,deinit 等价于 dealloc.在 deallocating 与 deallocated ...

  7. RxSwift之深入解析如何创建Observable序列

    一.emty 创建一个空的序列:本来序列事件是 Int 类型的,调用 emty 函数没有序列,只能 complete: let emtyOb = Observable<Int>.empty ...

  8. RxSwift之深入解析核心逻辑Observable的底层原理

    一.前言 现有一段 RxSwift 使用序列并监听序列消息发送的示例代码,如下所示: // 创建序列let ob = Observable<Any>.create { (observer) ...

  9. RxSwift之深入解析Using操作的应用和原理

    一.前言 ReactiveX 官方文档 对于 Using 的描述如下: create a disposable resource that has the same lifespan as the O ...

最新文章

  1. 计算机社团优秀成员申请书,优秀社团的成员申请书
  2. Stanford UFLDL教程 栈式自编码算法
  3. ssh secure shell
  4. Buuctf(pwn) picoctf_2018_rop chain 栈溢出
  5. 亲加通讯云郝飞:探讨直播低延迟低流量的粉丝连麦技术
  6. hystrix原理_面试必问的SpringCloud实现原理图
  7. 为iOS7重新设计你的App
  8. wordpress页面里可不可以写php,WordPress开发中如何在html中包含php
  9. SQL Server-【知识与实战II】条件查询、比较运算符查询、模糊查询、枚举查询、范围查询、空值查询、多重条件查询
  10. 安装AX2012R3流程
  11. 细胞自动机,那是什么?
  12. 小学思维导图免费模板合集!家长必收藏
  13. 平板电脑可以用手写的计算机软件,平板电脑可以当手写板(绘图板)用吗?
  14. 【物联网】物联网关键技术与应用分析
  15. Cesium加载影像图
  16. nodejs获取时间戳
  17. 博弈:阿里巴巴与雅虎
  18. 提升Facebook触及率和互动率攻略 | 智能客服帮您抓住用户的心
  19. 哈希表——高效率的利器
  20. 逻辑回归模型——股票客户流失预警模型

热门文章

  1. Red hat下使用automake自动配置wxWidgets的makefile
  2. java工程师面试如何自我介绍
  3. Jmeter4.0----CSV Data Set Config_对输入参数进行参数化(13)
  4. Luogu P1198 [JSOI2008]最大数 线段树
  5. 用ASP实现简单的繁简转换
  6. 事编计算机网络管理专技如何评级,事业单位管理和专技岗位有什么区别?哪个有前途?...
  7. python pytest setupclass_简单了解pytest测试框架setup和tearDown
  8. redis可以存多少条数据_最新数据!在武汉14区排名多少可以上高中?精准定位...
  9. C语言学习之编程输入x,输出对应的y.
  10. python 字节和字符串区别,Python中字节串和字符串,不是一个概念没有区别之分...