Observable & Observer 既是可监听序列也是观察者
在我们所遇到的事物中,有一部分非常特别。它们既是可监听序列也是观察者。在Rx框架中定义了一些这样的辅助类型:AsyncSubject、ReplaySubject、BehaviorSubject、ControlProperty。
AsyncSubject:
//在序列产生完成事件后,发出最后一个元素(only one), 如果序列没有发出任何元素,那只有一个完成事件。如果产生了error事件而终止,那就不会发出任何元素,只发出一个error事件。
let subject = AsyncSubject<String>()
subject.subscribe { print("subscribe :", $0) }
.disposed(by: disposeBag)
subject.onNext("s1")
subject.onNext("s2")
subject.onCompleted()
subject.onError(NSError.init(domain: "error", code: 404, userInfo: nil))
//输出结果
subscribe : next(s2)
subscribe : completed
PublishSubject:
//只发送观察者订阅后的元素
let publish = PublishSubject<String>()
publish.subscribe { print("subscribe1:", $0) }
.disposed(by: disposeBag)
publish.onNext("p1")
publish.onNext("p2")
publish.subscribe { print("subscribe2:", $0) }
.disposed(by: disposeBag)
publish.onNext("p3")
publish.onNext("p4")
//输出结果
subscribe1: next(p1) subscribe1: next(p2) subscribe1: next(p3)
subscribe2: next(p3) subscribe1: next(p4) subscribe2: next(p4)
ReplaySubject:
//会发送全部的元素 bufferSize:n 会发送订阅前的n个元素
let replay = ReplaySubject<String>.create(bufferSize: 1)
replay.subscribe { print("subscribe1:", $0) }
.disposed(by: disposeBag)
replay.onNext("r1")
replay.onNext("r2")
replay.subscribe { print("subscribe2 :", $0) }
.disposed(by: disposeBag)
replay.onNext("r3")
replay.onNext("r4")
//输出结果
subscribe1: next(r1)
subscribe1: next(r2)
subscribe2 : next(r2)
subscribe1: next(r3)
subscribe2 : next(r3)
subscribe1: next(r4)
subscribe2 : next(r4)
BehaviorSubject:
//当观察者订阅时,会发送最新的元素,如果没有新元素则发出默认元素,然后发送后续的元素(类似ReplaySubject<String>.create(bufferSize: 1))
let behavior = BehaviorSubject(value: "b0")
behavior.subscribe { print("subscribe1:", $0) }
.disposed(by: disposeBag)
behavior.onNext("b1")
behavior.onNext("b2")
behavior.subscribe { print("subscribe2:",$0) }
.disposed(by: disposeBag)
behavior.onNext("b3")
behavior.onNext("b4")
//输出结果
subscribe1: next(b0)
subscribe1: next(b1)
subscribe1: next(b2)
subscribe2: next(b2)
subscribe1: next(b3)
subscribe2: next(b3)
subscribe1: next(b4)
subscribe2: next(b4)
ControlProperty:
//用于描述UI属性,不会产生error事件,一定在主线程(MainSchedulder)订阅,共享附加作用(暂不明)
let controlProperty = self.textFld.rx.text
let observer = self.titleLab.rx.text
controlProperty.bind(to: observer)
.disposed(by: disposeBag)
操作符
// satrtWith: 指定序列的元素顺序 类似数组中插入第一个元素
Observable.of("1", "2", "3")
.startWith("a")
.startWith("c")
.startWith("e")
.subscribe(onNext: {print($0)})
.disposed(by: disposeBag)
// merge: 将多个Observables 合并成一个,当其中一个序列发出一个元素时,新合并的序列就会将元素发出,如果有一个发出onError事件,合并序列就好终止
let sub1 = PublishSubject<String>()
let sub2 = PublishSubject<String>()
Observable.of(sub1, sub2)
.merge()
.subscribe { print("merge:", $0) }
.disposed(by: disposeBag)
sub1.onNext("m1")
sub2.onNext("m2")
sub1.onNext("m3")
sub1.onNext("m4")
sub2.onNext("m5")
sub2.onNext("m6")
//zip: 通过函数将多个(最多8个)序列的元素组合并发出结果,按照序列的索引数进行组合。新序列的第一个元素是由每一个源序列的第一个元素组成,因此返回元素数量由最小(元素数量最少)的那个序列决定
let z1 = PublishSubject<String>()
let z2 = PublishSubject<String>()
Observable.zip(z1, z2) {$0 + $1}
.subscribe { print("zip:", $0) }
.disposed(by: disposeBag)
z1.onNext("z1")
z1.onNext("z2")
z1.onNext("z3")
z2.onNext("z4")
z2.onNext("z5")
//combineLatest 和 zip类似 combineLatest会覆盖旧值
let combine1 = PublishSubject<String>()
let combine2 = PublishSubject<String>()
Observable.combineLatest(combine1, combine2) { $0 + $1 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
combine1.onNext("1")
combine2.onNext("A")
combine1.onNext("2")
combine2.onNext("B")
combine2.onNext("C")
combine2.onNext("D")
combine1.onNext("3")
combine1.onNext("4")
//map: 将源序列的每个元素通过函数进行转换,返回一个转换结果的新序列
Observable.of(1, 2, 3)
.map{ $0 + 100 }
.subscribe(onNext: {print("map:",$0)})
.disposed(by: disposeBag)
//flatMap: 当序列的元素本身拥有其他序列的时,可以将所有子序列的元素发送出来
let flat1 = BehaviorSubject(value: "0")
let flat2 = BehaviorSubject(value: "A")
let flatSubject = BehaviorSubject(value: flat1)
flatSubject.asObservable()
.flatMap { $0 }
.subscribe(onNext: { print("flatMap:",$0) })
.disposed(by: disposeBag)
flat1.onNext("1")
flatSubject.onNext(flat2)
flat2.onNext("B")
//scan: 9 + 10 -> 19 + 100 -> 119 + 1000 = 1119 通过函数得到的结果作为参数进行下一次计算,每次结果都会作为新元素发送出来
Observable.of(10, 100, 1000)
.scan(9) { param, newValue in
param + newValue
}
.subscribe(onNext: { print("scan:",$0) })
.disposed(by: disposeBag)
//filter: 过滤出符合条件的元素并发送出来
Observable.of(1,2,3,4,5,6,7,8,9,0)
.filter { $0 > 5 }
.subscribe(onNext: { print("filter:",$0) })
.disposed(by: disposeBag)
//distinctUntilChanged: 相邻的元素相同则只会发送一个
Observable.of("1", "2", "2", "2", "3", "3", "4", "5", "4")
.distinctUntilChanged()
.subscribe(onNext: { print("distinctUntilChanged:",$0) })
.disposed(by: disposeBag)
//elementAt: 发出序列中指定索引数的元素
Observable.of("g", "l", "a", "c", "i", "e", "r")
.element(at: 3)
.subscribe(onNext: { print("elementAt:",$0) })
.disposed(by: disposeBag)
//single: 只发出序列发出的第一个元素(或满足条件的第一个元素)。如果序列没有元素或者元素数量大于一,将抛出一个错误。
Observable.of("A", "B")
.single()
.subscribe(onNext: { print("single:",$0) })
.disposed(by: disposeBag)
Observable.of("C", "D")
.single { $0 == "D" }
.subscribe( onNext: { print("single2:",$0) } )
.disposed(by: disposeBag)
//take: 只从一个序列的开始发出指定数量的元素。 和signal相比,signal只能一个
Observable.of("A", "B", "C", "D")
.take(2)
.subscribe(onNext: { print("take:",$0) })
.disposed(by: disposeBag)
//takeLast: 仅从序列的末尾发出指定数量的元素
Observable.of("1", "2", "3", "4")
.takeLast(3)
.subscribe(onNext: { print("takeLast:",$0) })
.disposed(by: disposeBag)
//takeWhile: 只要指定条件的值为true,就从可观察序列的开始发出元素
Observable.of(1, 2, 3, 4, 5, 6)
.take(while: { $0 < 3 })
.subscribe(onNext: { print("takeWhile:",$0) })
.disposed(by: disposeBag)
//takeUntil: 从源序列发出元素,直到参考序列发出元素。页面销毁了,就不能获取值了(cell重用运用)
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.take(until: referenceSequence)
.subscribe(onNext: { print("takeUntil:",$0) })
.disposed(by: disposeBag)
sourceSequence.onNext("1")
sourceSequence.onNext("2")
sourceSequence.onNext("3")
referenceSequence.onNext("Done") // 参考序列发出元素,原序列就不发送了
sourceSequence.onNext("A")
sourceSequence.onNext("B")
sourceSequence.onNext("C")
//toArray: 将一个序列转换为一个数组,将该数组作为一个新的单元素序列发出,然后终止
Observable.range(start: 1, count: 10)
.toArray()
.subscribe{ print("toArray:",$0) }
.disposed(by: disposeBag)
//reduce: 从一个设置的初始化值开始,然后对一个序列发出的所有元素应用累加器闭包,并以单个元素序列的形式返回聚合结果 - 类似scan, 比较scan会发送所有的元素
Observable.of(10, 100, 1000)
.reduce(1, accumulator: +) // 1 + 10 + 100 + 1000 = 1111
.subscribe(onNext: { print("reduce:",$0) })
.disposed(by: disposeBag)
//concat: 以顺序方式连接来自一个序列的内部序列的元素,在从下一个序列发出元素之前,等待每个序列成功终止
// 用来控制顺序
let subject1 = BehaviorSubject(value: "A")
let subject2 = BehaviorSubject(value: "1")
let concatSubject = BehaviorSubject(value: subject1)
concatSubject.asObservable()
.concat()
.subscribe { print("concat:",$0) }
.disposed(by: disposeBag)
subject1.onNext("B")
subject1.onNext("C")
concatSubject.onNext(subject2)
subject2.onNext("打印不出来")
subject2.onNext("2")
subject2.onNext("OK吗")
subject1.onCompleted() // 必须要等subject1 完成了才能订阅到! 用来控制顺序 网络数据的异步
subject2.onNext("3")