合并操作
合并多个序列或者值成单个序列。
startWith
在序列触发值之前插入一个多个元素的特殊序列。
1 | let disposeBag = DisposeBag() |
最后插入的元素数组在最前面,如下图:
merge
把多个序列合并成单个序列,并按照事件触发的先后顺序,依次发射值。
1 | let disposeBag = DisposeBag() |
如图:
当其中某个序列发生了错误就会立即把错误发送到合并的序列并终止。
zip
把多个序列组合成到一起并触发一个值,但只有每一个序列都发射了一个值之后才会组合成一个新的值并发出来。
1 | let disposeBag = DisposeBag() |
如图:
combineLatest
获取两个序列的最新值,并通过某个函数对其进行处理,处理完之后返回一个新的发射值。
1 | let disposeBag = DisposeBag() |
如图:
combineLatest
还有一个变体可以接受一个数组,或者任何其他可被观察序列的集合。但是要求这些可被观察序列元素是同一类型。
1 | let disposeBag = DisposeBag() |
switchLatest
这个也是用来合并序列的,不过不同的是,每当一个新的序列发射时,原来序列将被丢弃。
1 | let disposeBag = DisposeBag() |
大家想想把这里的switchLatest
改成merge
会输出什么?
图例:
sample
当收到目标事件,就会从源序列取一个最新的事件,发送到序列,如果两次目标事件之间没有源序列的事件,则不发射值。
1 | let source = PublishSubject<Int>() |
转换操作
对当前序列的值进行转换发射一个新的序列。
map
和Swift
里面的map
类似,转换其中的每一个元素。
1 | let disposeBag = DisposeBag() |
faltMap
把当前序列的元素转换成一个新的序列,并把他们合并成一个序列,这个在我们的一个可被观察者序列本身又会触发一个序列的时候非常有用,比如发送一个新的网络请求。
1 | let disposeBag = DisposeBag() |
flatMapLatest
和faltMap
不同的是,flatMapLatest
在收到一个新的序列的时候,会丢弃原有的序列。那么我们把上面的代码里面的flatMap
改成flatMapLatest
会输出什么呢?
flatMapLatest
相当于map
和switchLatest
操作的组合。
scan
和Swift
里面的reduce
类似,给予一个初始值,依次对每个元素进行操作,最后返回操作的结果。
1 | let disposeBag = DisposeBag() |
如图:
过滤和条件操作
filter
和Swift
里面的filter
类似,用来过滤序列中指定条件的值。
1 | let disposeBag = DisposeBag() |
如图:
distinctUntilChanged
过滤掉连续发射的重复元素。
1 | let disposeBag = DisposeBag() |
elementAt
只发送指定位置的值。
1 | let disposeBag = DisposeBag() |
如图:
single
发送单个元素,或者满足条件的第一个元素,如果有多个元素或者没有元素都会抛出错误。
1 | Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵") |
如果这里只有一个元素,则不会报错。
1 | Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵") |
take
获取序列前多少个值。
1 | let disposeBag = DisposeBag() |
takeLast
获取序列后多少个值。
1 | let disposeBag = DisposeBag() |
takeWhile
发射值值到条件变成false,变成false后,后面满足条件的值也不会发射。
1 | let disposeBag = DisposeBag() |
如果在4
后面加了个1
会输出什么?
如图:
takeUntil
发射原序列,直到新的序列发射了一个值。
1 | let disposeBag = DisposeBag() |
如图:
skip
跳过开头指定个数的值。
1 | let disposeBag = DisposeBag() |
如图:
skipWhile
跳过满足条件的值到条件变成false,变成false后,后面满足条件的值也不会跳过。
1 | let disposeBag = DisposeBag() |
如果在4
后面加了个1
会输出什么?
如图:
skipWhileWithIndex
和skipWhile
类似,只不过带上了index
。
1 | let disposeBag = DisposeBag() |
skipUntil
和takeUntil
相反,跳过原序列,直到新序列发射了一个值。
1 | let disposeBag = DisposeBag() |
如图:
聚合操作
toArray
把一个序列转成一个数组,然后作为新的一个值发射。
1 | let disposeBag = DisposeBag() |
reduce
给一个初始值,然后和序列里的每个值进行运行,最后返回一个结果,然后把结果作为单个值发射出去。
1 | let disposeBag = DisposeBag() |
concat
串联多个序列,下一个序列必须等前一个序列完成才会发射出来。
1 | let disposeBag = DisposeBag() |
如图:
大家想一想下面会输出什么?
1 | let disposeBag = DisposeBag() |
连接操作
可连接的序列和一般序列没有不同,除了只有当调用connect()
之后才会开始发射值,通过这种方式,你可以等所有的订阅者订阅后才发射值。
先来看一个没有连接操作的例子:
1 | let interval = Observable<Int>.interval(2, scheduler: MainScheduler.instance) |
第一行代码是在指定的线程每隔一定的时间发射一个信号。
那么这里我们可以看到在第一个订阅者订阅后,每隔2秒会收到一个值,而后面一个订阅5秒后才收到第一个值0,所以两个订阅者接收到的值是不同步的。
看输出:
1 | Subscription: 1, Event: 0 |
publish
把一个序列转成一个可连接的序列。
首先来看一个没有连接的序列:
1 | let intSequence = Observable<Int>.interval(2, scheduler: MainScheduler.instance) |
结果如下:
1 | Subscription 1:, Event: 0 //第一个订阅者开始订阅 |
把第一行代码变成:
1 | let intSequence = Observable<Int>.interval(2, scheduler: MainScheduler.instance) |
加了个publish
后变成可连接序列了,但是并不会输出值,只有在调用connect
之后才会开始发射值。而且与前面不同的是,前面的Observable
被多次subscribe
就会被多次触发。publish + connect
的组合每次subscribe
不会导致Observable
重新针对observer
处理一遍。
所以如果上面的代码写成这样会输出什么?
1 | let intSequence = Observable<Int>.interval(2, scheduler: MainScheduler.instance) |
如图:
replay
把源序列转换可连接的序列,并会给新的订阅者发送之前bufferSize
个的值。
1 | let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance) |
如图:
multicast
传入一个Subject
,每当序列发射都会触发这个Subject
的发射。
1 | let subject = PublishSubject<Int>() |
错误操作
catchErrorJustReturn
捕获到错误的时候,返回指定的值,然后终止。
1 | let disposeBag = DisposeBag() |
catchError
捕获一个错误值,然后切换到新的序列。
1 | let disposeBag = DisposeBag() |
如图:
retry
捕获到错误的时候,重新订阅该序列。retry(_:)
表示最多重试多少次。 retry(3)
1 | let disposeBag = DisposeBag() |
如图:
调试操作
debug
打印所有的订阅者、事件、和处理。
1 | let disposeBag = DisposeBag() |
RxSwift.Resources.total
提供所有Rx
申请资源的数量,在检查内存泄露的时候非常有用。
1 | print(RxSwift.Resources.total) |