前言
在RxSwift
中,高阶函数也可以成为操作符,高阶函数可以帮助我们创建新的序列,或者变化组合原有的序列,从而生成一个新的序列。
转换操作符
1. map
map
操作符会通过传入一个函数闭包把原来的 Observable
序列转变为一个新的 Observable
序列,map
函数会将源序列的所有元素进行转换,返回一个新序列.
let disposeBag = DisposeBag() Observable.of(1, 2, 3) .map { $0 * 100} .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 100 200 300复制代码
2. flatMap
map
在做转换的时候容易出现“升维”的情况。即转变之后,从一个序列变成了一个序列的序列。而flatMap
操作符会对源Observable
的每一个元素应用一个转换方法,将他们转换成 Observables
。 然后将这些 Observables
的元素合并之后再发送出来。即又将其 降维成一个 Observable
序列。
Observable
的元素本身就拥有其他的 Observable
时,我们可以将所有子 Observables
的元素发送出来。 例子:
let disposeBag = DisposeBag() let Henry = BehaviorSubject(value: 1) let Jeannie = BehaviorSubject(value: 2) let Henry_Subject = BehaviorSubject(value: Henry) Henry_Subject.asObservable() .flatMap { $0 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext(3) Henry_Subject.onNext(Jeannie) Henry.onNext(5) Jeannie.onNext(6) //结果 1 3 2 5 6复制代码
3. flatMapLatest
flatMapLatest
操作符会将Observable
的元素转换成其他的 Observable
,然后取这些 Observables
中最新的一个。
flatMapLatest
操作符将源 Observable
的每一个元素应用一个转换方法,将他们转换成 Observables
。一旦转换出一个新的 Observable
,就只发出它的元素,旧的 Observables
的元素将被忽略掉。 flatMapLatest
与flatMap
的唯一区别是:flatMapLatest
只会接收最新的value
事件。flatMapLatest
实际上是map
和switchLatest
操作符的组合- 有
flatMapLatest
就会有flatMapFirst
,flatMapFirst
与flatMapLatest
正好相反:flatMapFirst
只会接收最初的value
事件。(该操作符可以防止重复请求: 比如点击一个按钮发送一个请求,当该请求完成前,该按钮点击都不应该继续发送请求。便可该使用flatMapFirst
操作符。)
例子:
let disposeBag = DisposeBag() let Henry = BehaviorSubject(value: 1) let Jeannie = BehaviorSubject(value: 2) let Henry_Subject = BehaviorSubject(value: Henry) Henry_Subject.asObservable() .flatMapLatest{ $0 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext(3) Henry_Subject.onNext(Jeannie) Jeannie.onNext(5) Henry.onNext(6) //结果: 1 3 2 5复制代码
4. concatMap
concatMap
操作符会将 Observable
的元素转换成其他的 Observable
,然后将这些 Observables
串连起来
concatMap
操作符将源 Observable
的每一个元素应用一个转换方法,将他们转换成 Observables
。然后让这些 Observables
按顺序的发出元素. concatMap
与flatMap
的唯一区别是:当前一个Observable
元素发送完毕后,后一个Observable
才可以开始发出元素。等待前一个Observable
产生完成事件后,才对后一个Observable
进行订阅。
例子:
let disposeBag = DisposeBag() let Henry = BehaviorSubject(value: 1) let Jeannie = BehaviorSubject(value: 2) let Henry_Subject = BehaviorSubject(value: Henry) Henry_Subject.asObservable() .concatMap{ $0 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext(3) Henry_Subject.onNext(Jeannie) Jeannie.onNext(5) Jeannie.onNext(6) Henry.onCompleted() //结果: 1 3 6复制代码
5. scan
scan
操作符会持续的将Observable
,然后发出每一次函数返回的结果
scan
操作符将对第一个元素应用一个函数,将结果作为第一个元素发出。然后,将结果作为参数填入到第二个元素的应用函数中,创建第二个元素。以此类推,直到遍历完全部的元素。也就是 scan
先给一个初始化的数,然后不断的拿前一个结果和最新的值进行处理操作。 例子:
let disposeBag = DisposeBag() Observable.of(1, 2, 3, 4, 5) .scan(0) { acum, elem in acum + elem } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果 1 3 6 10 15复制代码
6. reduce
reduce
操作符和scan
操作符还是有点类似的,reduce
操作符将对第一个元素应用一个函数。然后,将结果作为参数填入到第二个元素的应用函数中。以此类推,直到遍历完全部的元素后发出最终结果。
let disposeBag = DisposeBag() Observable.of(10, 20, 30) .reduce(0, accumulator: +) .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 60复制代码
7.toArray
toArray
操作符先把一个序列转成一个数组,并作为一个单一的事件发送,然后结束。
let disposeBag = DisposeBag() Observable.of(1, 2, 3) .toArray() .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: [1,2,3]复制代码
组合操作符
1. merge
merge
操作符会将多个Observables
合并成一个Observable
. 通过使用 merge 操作符可以将多个 Observables
合并成一个,当某一个 Observable
发出一个元素时,它就将这个元素发出。
Observable
发出一个 onError
事件,那么被合并的 这个 Observable
也会将这个 onError
事件发出,并且立即终止序列。 值得注意的是这里被合并的序列元素必须是同类型的。
例子:
let disposeBag = DisposeBag() let Henry = PublishSubject () let Jeannie = PublishSubject () Observable.of(Henry, Jeannie) .merge() .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext(1) Henry.onNext(2) Jeannie.onNext(100) Henry.onNext(3) Henry.onNext(4) Jeannie.onNext(1000) //结果: 1 2 100 3 4 1000 复制代码
2. startWith
startWith
操作符会在 Observable
头部插入一些事件元素。即发出Observable
的事件元素之前,会先发出这些预先插入的事件元素。
Observable
头部分多次插入事件元素,那么这些事件元素会一直在 Observable
头部追加,也就是后插入的先发出来。 例子:
let disposeBag = DisposeBag() Observable.of("1", "2") .startWith("A") .startWith("B") .startWith("a", "b") .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: a b B A 1 2复制代码
3. zip
zip
操作符可将多个 Observables
的元素组合压缩,而且它会等到每个Observable
元素事件一一对应地凑齐之后再合并,然后将每一个组合的结果元素发出来。
zip
操作符最多可以将8个 Observables
的元素通过一个函数组合起来,然后将这个组合的结果发出来。它会严格的按照序列的索引数进行组合。例如,返回的 Observable
的第一个元素,是由每一个源 Observables
的第一个元素组合出来的。它的第二个元素 ,是由每一个源 Observables
的第二个元素组合出来的。它的第三个元素 ,是由每一个源 Observables
的第三个元素组合出来的,以此类推。它的元素数量等于源 Observables
中元素数量最少的那个。 例子:
let disposeBag = DisposeBag() let Henry = PublishSubject() let Jeannie = PublishSubject () Observable.zip(Henry, Jeannie) { $0 + $1 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext("1") Jeannie.onNext("A") Henry.onNext("2") Jeannie.onNext("B") Jeannie.onNext("C") Henry.onNext("3") Henry.onNext("4") //结果: 1A 2B 3C复制代码
zip
操作符常常用在整合网络请求上。 比如我们想同时发送两个请求,只有当两个请求都成功后,再将两者的结果整合起来继续往下处理。这个功能就可以通过 zip
来实现。
4. combineLatest
combineLatest
操作符同样是将多个Observables
序列元素进行合并。但与zip
不同的是,每当任意一个 Observable
有新的事件发出时,它会将每个Observable
序列的最新的一个事件元素进行合并,然后发送这个组合出来的元素。(前提是,这些 Observables
曾经发出过元素)。
例子:
let disposeBag = DisposeBag() let Henry = PublishSubject() let Jeannie = PublishSubject () Observable.combineLatest(Henry, Jeannie) { $0 + $1 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext("1") Jeannie.onNext("A") Henry.onNext("2") Jeannie.onNext("B") Jeannie.onNext("C") Henry.onNext("3") Henry.onNext("4") //结果: 1A 2A 2B 2C 3C 4C复制代码
5. concat
concat
操作符将多个 Observables
按顺序串联起来,并且只有当前面一个 Observable
序列发出了 completed
事件,才会开始发送下一个 Observable
序列事件。
let disposeBag = DisposeBag() let Henry = BehaviorSubject(value: 1) let Jeannie = BehaviorSubject(value: 2) let Henry_Subject = BehaviorSubject(value: Henry) Henry_Subject.asObservable() .concat() .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext(3) Henry_Subject.onNext(Jeannie) Jeannie.onNext(5) Jeannie.onNext(6) Henry.onCompleted() Jeannie.onNext(7) //结果: 1 3 6 7复制代码
感觉concat
操作符和concatMap
操作符比较相似,它们都是要等到前面一个 Observable
序列发出了 completed
事件,才会开始发送下一个 Observable
序列事件。
6. withLatestFrom
withLatestFrom
操作符会将两个 Observables
最新的元素通过一个函数组合起来,当第一个 Observable
发出一个元素,就将组合后的元素发送出来。
let disposeBag = DisposeBag() let firstSubject = PublishSubject() let secondSubject = PublishSubject () firstSubject .withLatestFrom(secondSubject) { (first, second) in return first + second } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) firstSubject.onNext("A️") secondSubject.onNext("1") firstSubject.onNext("B") //结果: B1复制代码
过滤条件操作符
1. filter
filter
操作符就是用来过滤掉某些不符合要求的事件,仅仅发出Observable
中通过判定的元素。
例子:
let disposeBag = DisposeBag() Observable.of(11, 22, 3, 8, 2, 1) .filter { $0 > 10 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 11 22复制代码
2. take
take
操作符仅仅从 Observable
中发出头n
个元素,在满足数量之后会自动发送 .completed
事件。
例子:
let disposeBag = DisposeBag() Observable.of(1, 2, 3, 4, 5, 6) .take(3) .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 1 2 3复制代码
3. takeLast
takeLast
操作符与take
操作符类似,实现仅发送 Observable
序列中的后n
个元素,忽略前面的元素。
例子:
let disposeBag = DisposeBag() Observable.of(1, 2, 3, 4, 5, 6) .takeLast(3) .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 4 5 6复制代码
4. takeWhile
takeWhile
操作符会依次判断 Observable
序列的每一个值是否满足给定的条件。 当第一个不满足条件的值出现时,它便自动完成。
let disposeBag = DisposeBag() Observable.of(2, 3, 4, 5, 6) .takeWhile { $0 < 4 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 2 3复制代码
5. takeUntil
takeUntil
操作符会忽略掉在第二个Observable
产生事件后发出的那部分元素。也就是,takeUntil
操作符会观测源Observable
,它同时观测第二个 Observable
。一旦第二个 Observable
发出一个元素或者产生一个终止事件,那么源Observable
将自动完成,停止发送事件。
let disposeBag = DisposeBag() let Henry = PublishSubject() let Jeannie = PublishSubject () Henry .takeUntil(Jeannie) .subscribe { print($0) } .disposed(by: disposeBag) Henry.onNext("Good") Henry.onNext("Lucky") Jeannie.onNext("Bug") Henry.onNext("Tnanks") Henry.onNext("a lot") //结果: next(Good) next(Lucky) completed复制代码
6. skip
skip
操作符用于跳过源 Observable
序列发出的前n
个元素事件。
let disposeBag = DisposeBag() Observable.of(1, 2, 3, 4) .skip(2) .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 3 4复制代码
7. skipWhile
skipWhile
操作符可以让你忽略源 Observable
中头几个满足条件的事件。
例子:
let disposeBag = DisposeBag() Observable.of(2, 3, 4, 5, 6) .skipWhile { $0 < 5 } .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 5 6复制代码
8. skipUntil
同上面的 takeUntil
类似,skipUntil
除了订阅源 Observable
外,通过 skipUntil
方法我们还可以监视另外一个 Observable
。skipUntil
操作符会跳过Observable
中头几个元素,直到另一个 Observable
发出一个元素。
let disposeBag = DisposeBag() let Henry = PublishSubject () let Jeannie = PublishSubject () Henry .skipUntil(Jeannie) .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) Henry.onNext(1) Henry.onNext(2) //开始接收消息 Jeannie.onNext(0) Henry.onNext(3) Henry.onNext(4) //仍然接收消息 Jeannie.onNext(0) Henry.onNext(5) //结果: 3 4 5复制代码
9. elementAt
elementAt
操作符只发出 Observable
中的第 n
个元素,即是只处理指定位置的元素事件
let disposeBag = DisposeBag() Observable.of(1, 2, 3, 4) .elementAt(2) .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果: 3复制代码
10. distinctUntilChanged
distinctUntilChanged
操作符用于过滤掉连续重复的事件。如果后一个元素和前一个元素是相同的,那么这个元素将不会被发出来。如果后一个元素和前一个元素不相同,那么这个元素才会被发出来。
例子:
let disposeBag = DisposeBag() Observable.of(1, 2, 1, 1, 1, 3) .distinctUntilChanged() .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) //结果 1 2 1 3复制代码
11.amb
amb
操作符在多个源 Observables
中, 取第一个发出元素或产生事件的 Observable
,这个事件可以是一个 next
,error
或者 completed
事件,然后就只发出这个Observable
的元素事件,忽略掉其他的Observables
。
let disposeBag = DisposeBag() let subject1 = PublishSubject () let subject2 = PublishSubject () let subject3 = PublishSubject () subject1 .amb(subject2) .amb(subject3) .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) subject2.onNext(1) subject1.onNext(20) subject2.onNext(2) subject1.onNext(40) subject3.onNext(0) subject2.onNext(3) subject1.onNext(60) subject3.onNext(0) subject3.onNext(0) //结果: 1 2 3复制代码
总结
关于RxSwift
的高阶函数先总结这么一部分。其实通过这些简单的示例来看,这些操作符在我们对序列进行操作的时候会有很大的帮助,而且使用简单。学好RxSwift
,走遍天下都不怕。
感谢