Tantan Fu

May 04, 2016

RxSwift 速查手册

本文档内容来自于 RxSwift 的 Playground。记录大多数 ReactiveX 的概念和操作符。
(部分翻译和注解来自 ReactiveX 文档中文翻译)

为什么使用 RxSwift?

我们写的很多代码实际上是为了解决和响应外部事件。当用户操作一个控件的时候,我们需要使用 @IBAction 来响应事件。我们需要观察通知来检测键盘改变位置。当 URL Sessions 带着响应的数据返回时,我们需要提供闭包来执行我们的操作。我们还需要使用 KVO 来检测变量的值改变。这些大量的编写机制使得我们的代码结构变的更加复杂。如果有一种统一的编写机制来完成所有的这些调用 / 响应代码是不是更棒呢?Rx 就是为解决这些问题而生的。

Observable

理解 RxSwift 的关键是理解 Observable 的概念。要理解它的创建,操作以及为了对变化做出响应操作而进行的订阅(subscribe)。

创建和订阅 Observable

要理解本框架,第一步需要理解如何创建 Observable。有很多函数可以创建 Observable。
创建 Observable 之后,如果没有订阅者订阅该 observable,那么什么事情也不会发生,所以我们将同时解释创建和订阅。

empty

empty 创建一个空的序列。它仅发送 .Completed 消息。
运行结果:

never

never 创建一个序列,该序列永远不会发送消息,.Completed 消息也不会发送。
运行结果:

just

just 代表只包含一个元素的序列。它将向订阅者发送两个消息,第一个消息是其中元素的值,另一个是 .Completed
运行结果:

sequenceOf

sequenceOf 通过固定数目的元素创建一个序列
运行结果:

toObservable

toObservable 在一个数组的基础上创建一个序列
运行结果:

create

create 使用 Swift 闭包来创建一个序列。该例子中,创建了 just 操作符的自定义版本。
运行结果:

generate

generate 创建的序列可以自己生成它的值,并且在之前值的基础上来判断什么时候结束。
运行结果:

error

创建一个不发送任何 item 的 Observable,以 error 中指
运行结果:

deferred

直到 observer 订阅之后才创建 Observable,并且为每一个 observer 创建一个全新的 Observable do not create the Observable until the observer subscribes, and create a fresh Observable for each observer
notion image
运行结果:
在 RxCocoa 库中还有很多其他非常有用的方法,例如:
  • rx_observe 存在于所有 NSObject 子类中,封装了 KVO
  • rx_tap 存在于 button 中,封装了 @IBActions
  • rx_notification 封装了 NotificationCenter
Subject 可以看成是一个桥梁或者代理,在某些 ReactiveX 实现中,它同时充当了 Observer 和 Observable 的角色。因为它是一个 Observer,它可以订阅一个或多个 Observable;又因为它是一个 Observable,它可以转发它收到 (Observe) 的数据,也可以发射新的数据。
辅助函数:

PublishSubject

PublishSubject 只会把在订阅发生的时间点之后来自原始 Observable 的数据发射给观察者。
notion image
notion image
运行结果:

ReplaySubject

ReplaySubject 会发射所有来自原始 Observable 的数据给观察者,无论它们是何时订阅的。当一个新的 observer 订阅了一个 ReplaySubject 之后,他将会收到当前缓存在 buffer 中的数据和这之后产生的新数据。在下面的例子中,缓存大小为 1 所以 observer 将最多能够收到订阅时间点之前的一个数据。例如,Subscription: 2 能够收到消息 "b",而这个消息是在他订阅之前发送的,但是没有办法收到消息 "a" 因为缓存的容量小于 2
notion image
运行结果:

BehaviorSubject

当观察者订阅 BehaviorSubject 时,它开始发射原始 Observable 最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始 Observable 的数据。
notion image
notion image
运行结果:

Variable

Variable 封装了 BehaviorSubject。使用 variable 的好处是 variable 将不会显式的发送 Error 或者 Completed。在 deallocated 的时候,Variable 会自动的发送 complete 事件。
运行结果:

变换操作

下面列出了可用于对 Observable 发射的数据执行变换操作的各种操作符。

map / select

对序列的每一项都应用一个函数来变换 Observable 发射的数据序列
notion image
运行结果:

flatMap

将每个 Obserable 发射的数据变换为 Observable 的集合,然后将其 “拍扁”(降维 flatten)成一个 Observable。
notion image
运行结果:

scan

对 Observable 发射的每一项数据应用一个函数,然后按顺序依次发射每一个值
notion image
运行结果:

过滤操作

从源 Observable 中选择特定的数据发送

filter

只发送 Observable 中通过特定测试的数据
notion image
运行结果:

distinctUntilChanged

过滤掉连续重复的数据
notion image
运行结果:

take

仅发送 Observable 的前 n 个数据项
notion image
运行结果:

结合操作 (Combination operators)

将多个 Observable 结合成一个 Observable

startWith

在数据序列的开头增加一些数据
notion image
运行结果:

combineLatest

当两个 Observables 中的任何一个发射了一个数据时,通过一个指定的函数组合每个 Observable 发射的最新数据(一共两个数据),然后发射这个函数的结果
notion image
运行结果:
为了能够产生结果,两个序列中都必须保证至少有一个元素
运行结果:
Combine latest 有超过 2 个参数的版本
运行结果:
Combinelatest 可以作用于不同数据类型的序列
运行结果:
combineLatest 方法可以在 Array 上使用,数组元素类型必须遵循 ObservableType 协议 数组中的元素类型必须为 Observables

zip

使用一个函数组合多个 Observable 发射的数据集合,然后再发射这个结果 (从序列中依次取数据)
notion image
运行结果:
运行结果:
运行结果:

merge

合并多个 Observables 的组合成一个
notion image
运行结果:
运行结果:

switchLatest

将一个发射多个 Observables 的 Observable 转换成另一个单独的 Observable,后者发射那些 Observables 最近发射的数据项
Switch 订阅一个发射多个 Observables 的 Observable。它每次观察那些 Observables 中的一个,Switch 返回的这个 Observable 取消订阅前一个发射数据的 Observable,开始发射最近的 Observable 发射的数据。注意:当原始 Observable 发射了一个新的 Observable 时(不是这个新的 Observable 发射了一条数据时),它将取消订阅之前的那个 Observable。这意味着,在后来那个 Observable 产生之后到它开始发射数据之前的这段时间里,前一个 Observable 发射的数据将被丢弃
notion image
运行结果:

Error Handling Operators

下面的操作符帮助我们从 Observable 发射的 error 通知做出响应或者从错误中恢复。

catchError

收到 Error 通知之后,转而发送一个没有错误的序列。
notion image
运行结果:
运行结果:

retry

如果原始 Observable 遇到错误,重新订阅,心里默念,不会出错不会出错…
notion image
运行结果:

Observable Utility Operators

下面的操作符可以当做一个工具集,方便操作 Observable

subscribe

运行结果:
下面是几个 subscribe 操作符的变体

subscribeNext

运行结果:

subscribeCompleted

运行结果:

subscribeError

运行结果:

doOn

注册一个操作来监听事件的生命周期 (register an action to take upon a variety of Observable lifecycle events)
notion image
运行结果:

条件和布尔操作(Conditional and Boolean Operators)

下面的操作符可用于根据条件发射或变换 Observables,或者对它们做布尔运算:

takeUntil

当第二个 Observable 发送数据之后,丢弃第一个 Observable 在这之后的所有消息。
notion image
运行结果:

takeWhile

发送原始 Observable 的数据,直到一个特定的条件为 false
notion image
运行结果:

算数和聚合 (Mathematical and Aggregate Operators)

concat

合并两个或者以上的 Observable 的消息,并且这些消息的发送时间不会交叉。(队列先后顺序不会交叉)
notion image
运行结果:

reduce

按顺序对 Observable 发射的每项数据应用一个函数并发射最终的值。Reduce 操作符对原始 Observable 发射数据的第一项应用一个函数,然后再将这个函数的返回值与第二项数据一起传递给函数,以此类推,持续这个过程知道原始 Observable 发射它的最后一项数据并终止,此时 Reduce 返回的 Observable 发射这个函数返回的最终值。与数组序列的 reduce 操作类似。
notion image
运行结果:

Copyright © 2023 Tantan Fu