前言
本章节的介绍操作主要是是将多个观察序列合成一个观察序列
Combination Operators
-
startWith
在源观察序列的元素之前发出元素,也可以理解为元队列的元素之前插入元素。并且每次不同的startWith发出或者插入的元素类似一种栈结构,后进先出的,但是在当前的startWith多个元素是不具有这种方式,还是按照队列的先进先出的
example("startWith") {
let disposeBag = DisposeBag()
Observable.of("🐶", "🐱", "🐭", "🐹")
.startWith("1️⃣")
.startWith("2️⃣")
.startWith("3️⃣", "🅰️", "🅱️")
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}
// 控制台打印的结果:
--- startWith example ---
3️⃣
🅰️
🅱️
2️⃣
1️⃣
🐶
🐱
🐭
🐹
-
merger
将多个观察序列合成为一个新的观察序列,新序列发出按照源序列发出(或者说插入,添加)元素的顺序发出
example("merge") {
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
Observable.of(subject1, subject2)
.merge()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("🅰️")
subject1.onNext("🅱️")
subject2.onNext("①")
subject2.onNext("②")
subject1.onNext("🆎")
subject2.onNext("③")
}
// 控制台打印的结果:
--- merge example ---
🅰️
🅱️
①
②
🆎
③
- ** zip **
和merger有点相似,也是将最多8个序列合成一个序列,但是zip可以将两个序列的对应顺序的元素进行合并,如果某个序列相应的顺序没有元素,则该顺序的所有序列的元素不会进行合并
上文翻译的顺序我自认为可以理解为索引,比如队列a b c,只有a、b、c这三个序列的索引n都有元素的之后才会将三者进行合并,只要一个序列的索引n没有元素就,那么该索引n下的元素均不合并
example("zip") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
Observable.zip(stringSubject, intSubject) { stringElement, intElement in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
stringSubject.onNext("🅰️")
stringSubject.onNext("🅱️")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("🆎")
intSubject.onNext(3)
}
// 控制台打印的结果:
--- zip example ---
🅰️ 1
🅱️ 2
🆎 3
// 本文不作者修改的程序1
example("zip") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
Observable.zip(stringSubject, intSubject) { stringElement, intElement in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
stringSubject.onNext("🅰️")
stringSubject.onNext("🅱️")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("🆎")
intSubject.onNext(3)
// 这里添加一个事件元素
intSubject.onNext(4)
}
// 控制台打印的结果:
--- zip example ---
🅰️ 1
🅱️ 2
🆎 3
// 本文不作者修改的程序2
example("zip") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
let intSubject2 = PublishSubject<Int>()
Observable.zip(stringSubject, intSubject, intSubject2) { stringElement, intElement, intSubject2 in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
stringSubject.onNext("🅰️")
stringSubject.onNext("🅱️")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("🆎")
intSubject.onNext(3)
intSubject.onNext(4)
}
// 控制台打印的结果:
--- zip example ---
修改程序解释:
在官方的演示程序后面我添加了两个修改的程序
1.intSubject.onNext(4)
,添加这一句,但是控制台没有打印,因为stringSubject没有事件元素与其配对,故没有打印
2.多添加一个观察序列intSubject2
,但是由于intSubject2
并没有添加任何事件元素,这意味着三个观察序列每次所以都不能成功配对,故控制台打印为空
-
combineLatest
合并最多8个观察者序列,此操作是将每个序列最新的元素进行合并,而且在某个序列有新元素添加的时候也会执行同样的合并操作,并且新元素也会找其他序列的最新的元素进行和并购,引用官方的一张演示图,能更好的理解此操作
example("combineLatest") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
Observable.combineLatest(stringSubject, intSubject) { stringElement, intElement in
" \(intElement)\(stringElement)"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
intSubject.onNext(1)
stringSubject.onNext("A")
stringSubject.onNext("B")
intSubject.onNext(2)
stringSubject.onNext("C")
stringSubject.onNext("D")
intSubject.onNext(3)
intSubject.onNext(4)
intSubject.onNext(5)
}
// 控制台打印的结果:
--- combineLatest example ---
1A
1B
2B
2C
2D
3D
4D
5D
combineLatest
同样适用Array(或者其他的观察者序列的集合)的操作,但是要求序列集合类型必须一致,即Observer<T>的T是一种类型,否则编译前就会报错
example("Array.combineLatest") {
let disposeBag = DisposeBag()
let stringObservable = Observable.just("❤️")
let fruitObservable = Observable.from(["🍎", "🍐", "🍊"])
let animalObservable = Observable.of("🐶", "🐱", "🐭", "🐹")
Observable.combineLatest([stringObservable, fruitObservable, animalObservable]) {
"\($0[0]) \($0[1]) \($0[2])"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}
// 控制台打印的结果:
--- Array.combineLatest example ---
❤️ 🍎 🐶
❤️ 🍐 🐶
❤️ 🍐 🐱
❤️ 🍊 🐱
❤️ 🍊 🐭
❤️ 🍊 🐹
-
switchLatest
官方翻译为:将Observable序列发射的元素转换为Observable序列,并从最近的内部Observable序列中发出元素
本文作者注:官方的解释较为模糊,个人理解为switch是一个切换功能,用在序列元素也是一个观察序列的场景,假设将序列的序列定义oss,将序列定义为os,在oss的元素值设置为os1的时候,则响应os1的事件元素,当oss的元素值设置为os2的时候,此时响应os2的事件元素,此时os1即便有事件元素发出也不响应,当oss的元素值再切换到os1的时候,则再去相应os1的事件元素
/*:
> Because the `combineLatest` variant that takes a collection passes an array of values to the selector function, it requires that all source `Observable` sequences are of the same type.
----
## `switchLatest`
Transforms the elements emitted by an `Observable` sequence into `Observable` sequences, and emits elements from the most recent inner `Observable` sequence. [More info](http://reactivex.io/documentation/operators/switch.html)
![](http://upload-images.jianshu.io/upload_images/954728-c0141794880b5a6f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
*/
example("switchLatest") {
let disposeBag = DisposeBag()
let subject1 = BehaviorSubject(value: "⚽️")
let subject2 = BehaviorSubject(value: "🍎")
let variable = Variable(subject1)
variable.asObservable()
.switchLatest()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("🏈")
subject1.onNext("🏀")
variable.value = subject2
subject1.onNext("⚾️")
subject2.onNext("🍐")
}
// 控制台打印的结果:
--- switchLatest example ---
⚽️
🏈
🏀
🍎
🍐
此官方实例中⚾️没有打印出来,因为variable(即oss)将值切换为subject2(即os2)之后,subject1(即os1)的值⚾️对subject2没有作用,故Variable不相应⚾️,为了让大家更易于理解switchLatest,我在官方的代码最后加一句
variable.value = subject1
,即将variable的值切换回subject1,则subjec1的事件元素⚾️将会被相应:
example("switchLatest") {
let disposeBag = DisposeBag()
let subject1 = BehaviorSubject(value: "⚽️")
let subject2 = BehaviorSubject(value: "🍎")
let variable = Variable(subject1)
variable.asObservable()
.switchLatest()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("🏈")
subject1.onNext("🏀")
variable.value = subject2
subject1.onNext("⚾️")
subject2.onNext("🍐")
variable.value = subject1
}
// 控制台打印的结果:
--- switchLatest example ---
⚽️
🏈
🏀
🍎
🍐
⚾️