本文着重介绍RxSwift高阶函数的使用,高阶函数很多,但没必要所有都熟练记忆,比较重要的能够熟练记忆并使用,不常用的用到了临时查询即可。
一、组合类操作符
1.startWith
在开始从可观察源发出元素之前,发出指定的元素序列。
Observable.of("1", "2", "3", "4")
.startWith("A")
.startWith("B")
.startWith("C", "a", "b")
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//输出: CabBA1234
2.merge
将源可观察序列中的元素组合成一个新的可观察序列,并将像每个源可观察序列发出元素一样发出每个元素。
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
// merge subject1和subject2
Observable.of(subject1, subject2)
.merge()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("H")
subject1.onNext("e")
subject2.onNext("l")
subject2.onNext("l")
subject1.onNext("o")
subject2.onNext("")
//输出:Hello
注: 任何一个响应都会勾起新序列响应
3.zip
将指定个数的源可观测序列组合成一个新的可观测序列,并将从组合的可观测序列中发射出对应索引处每个源可观测序列的元素。
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("H")
stringSubject.onNext("e") //到这里存储了H、o但是不会响应,除非另一个响应
intSubject.onNext(1) // 输出一个
intSubject.onNext(2) // 输出另一个
stringSubject.onNext("l") // 存一个
intSubject.onNext(3) // 输出一个
//只有两个序列同时有值的时候才会响应,否则存值
注: 只有两个序列同时有值的时候才会响应,否则存值。
4.combineLatest
将指定个数的源可观测序列组合成一个新的观测序列,并将最近的元素覆盖。
5.switchLatest
将可观察序列发出的元素转换为可观察序列,并从最近的内部可观察序列发出元素。
二、映射类操作符
1.map
转换闭包应用于可观察序列发出的元素,并返回转换后的元素的新可观察序列。
let ob = Observable.of(1,2,3,4)
ob.map { (number) -> Int in
return number+2
}
.subscribe{
print("\($0)")
}
.disposed(by: disposeBag)
2.flatMap & flatMapLatest
将可观测序列发射的元素转换为可观测序列,并将两个可观测序列的发射合并为一个可观测序列。
例如,当你有一个可观察的序列,它本身发出可观察的序列,你想能够对任何一个可观察序列的新发射做出反应(序列中序列:比如网络序列中还有模型序列)
flatMap和flatMapLatest的区别是,flatMapLatest只会从最近的内部可观测序列发射元素。
flatMapLatest实际上是map和switchLatest操作符的组合。
let boy = LGPlayer(score: 100)
let girl = LGPlayer(score: 90)
let player = BehaviorSubject(value: boy)
player.asObservable()
.flatMap { $0.score.asObservable() } // 本身score就是序列 模型就是序列中的序列
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
boy.score.onNext(60)
player.onNext(girl)
boy.score.onNext(50)
boy.score.onNext(40)// 如果切换到 flatMapLatest 就不会打印
girl.score.onNext(10)
girl.score.onNext(0)
3.scan
从初始就带有一个默认值开始,然后对可观察序列发出的每个元素应用累加器闭包,并以单个元素可观察序列的形式返回每个中间结果。这里主要强调序列值之间的关系。
Observable.of(10, 100, 1000)
.scan(2) { aggregateValue, newValue in
aggregateValue + newValue // 10 + 2 , 100 + 10 + 2 , 1000 + 100 + 2
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
三、过滤条件操作符
1.filter
仅从满足指定条件的可观察序列中发出那些元素。
Observable.of(1,2,3,4,5,6,7,8,9,0)
.filter { $0 % 2 == 0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
2.distincUntilChanged
抑制可观察序列发出的顺序重复元素。
Observable.of("1", "2", "2", "2", "3", "3", "4")
.distinctUntilChanged()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
3.elementAt
仅在可观察序列发出的所有元素的指定索引处发出元素。
Observable.of("C", "o", "o", "c", "i")
.elementAt(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
4.single
只发出可观察序列发出的第一个元素(或满足条件的第一个元素)。如果可观察序列发出多个元素,将抛出一个错误。
Observable.of("Apple", "Banana")
.single()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Observable.of("Apple", "Banana")
.single { $0 == "Banana" }
.subscribe { print($0) }
.disposed(by: disposeBag)
5.take
只从一个可观察序列的开始发出指定数量的元素。
Observable.of("A", "B","C", "D")
.take(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
6.takeLast
仅从可观察序列的末尾发出指定数量的元素。
Observable.of("A", "B","C", "D")
.takeLast(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
7.takeWhile
只要指定条件的值为true,就从可观察序列的开始发出元素
Observable.of(1, 2, 3, 4, 5, 6)
.takeWhile { $0 < 3 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
8.takeUntil
从源可观察序列发出元素,直到参考可观察序列发出元素.这个要重点,应用非常频繁 比如我页面销毁了,就不能获取值了(cell重用运用)。
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.takeUntil(referenceSequence)
.subscribe { print($0) }
.disposed(by: disposeBag)
sourceSequence.onNext("A")
sourceSequence.onNext("B")
sourceSequence.onNext("C")
referenceSequence.onNext("Stop-Condition")
//条件一出来,下面就走不了
sourceSequence.onNext("D")
sourceSequence.onNext("E")
sourceSequence.onNext("F")
9.skip
跳过指定个数的元素,开始发出元素。从源可观察序列发出元素,直到参考可观察序列发出元素.这个要重点,应用非常频繁 不用解释 textfiled 都会有默认序列产生。
Observable.of(1, 2, 3, 4, 5, 6)
.skip(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
10.skipWhile
从满足条件的位置开始发出元素。
Observable.of(1, 2, 3, 4, 5, 6)
.skipWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
11.skipUntil
抑制从源可观察序列发出元素,直到参考可观察序列发出元素。
代码类似takeUntil。
四、集合控制操作符
1.toArray
将一个可观察序列转换为一个数组,将该数组作为一个新的单元素可观察序列发出,然后终止。
Observable.range(start: 1, count: 10)
.toArray()
.subscribe { print($0) }
.disposed(by: disposeBag)
2.reduce
从一个设置的初始化值开始,然后对一个可观察序列发出的所有元素应用累加器闭包,并以单个元素可观察序列的形式返回聚合结果。类似scan。
Observable.of(10, 100, 1000)
.reduce(1, accumulator: +) // 1 + 10 + 100 + 1000 = 1111
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
3.contact
以顺序方式连接来自一个可观察序列的内部可观察序列的元素,在从下一个序列发出元素之前,等待每个序列成功终止。用来控制顺序。
let subject1 = BehaviorSubject(value: "Apple")
let subject2 = BehaviorSubject(value: "1")
let subjectsSubject = BehaviorSubject(value: subject1)
subjectsSubject.asObservable()
.concat()
.subscribe { print($0) }
.disposed(by: disposeBag)
subject1.onNext("Banana")
subject1.onNext("Orange")
subjectsSubject.onNext(subject2)
subject2.onNext("打印不出来")
subject2.onNext("2")
subject1.onCompleted() // 必须要等subject1 完成了才能订阅到! 用来控制顺序 网络数据的异步
subject2.onNext("3")
五、从可观察对象的错误通知中恢复的操作符
1.catchErrorJustReturn
从错误事件中恢复,方法是返回一个可观察到的序列,该序列发出单个元素,然后终止。
let sequenceThatFails = PublishSubject<String>()
sequenceThatFails
.catchErrorJustReturn("Apple")
.subscribe { print($0) }
.disposed(by: disposeBag)
sequenceThatFails.onNext("Banana")
sequenceThatFails.onNext("Orange") // 正常序列发送成功的
sequenceThatFails.onError(self)
2.catchError
通过切换到提供的恢复可观察序列,从错误事件中恢复
let recoverySequence = PublishSubject<String>()
sequenceThatFails
.catchError {
print("Error:", $0)
return recoverySequence // 获取到了错误序列-我们在中间的闭包操作处理完毕,返回给用户需要的序列(showAlert)
}
.subscribe { print($0) }
.disposed(by: disposeBag)
sequenceThatFails.onNext("Apple")
sequenceThatFails.onNext("Banana") // 正常序列发送成功的
sequenceThatFails.onError(lgError) // 发送失败的序列
recoverySequence.onNext("Orange”)
3.retry
通过无限地重新订阅可观察序列来恢复重复的错误事件
4.retry( _: )
通过重新订阅可观察到的序列,重复地从错误事件中恢复,直到重试次数达到max未遂计数
六、Debug Rx流程操作符
1.debug
打印所有订阅、事件和处理。
var count = 1
let sequenceThatErrors = Observable<String>.create { observer in
observer.onNext("A")
observer.onNext("B")
observer.onNext("C")
if count < 5 {
observer.onError(self.lgError)
print("错误序列来了")
count += 1
}
observer.onNext("D")
observer.onNext("E")
observer.onNext("F")
observer.onCompleted()
return Disposables.create()
}
sequenceThatErrors
.retry(3)
.debug()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
2.RxSwift.Resources.total
提供所有Rx资源分配的计数,这对于在开发期间检测泄漏非常有用。
七、链接操作符
1.multicast
将源可观察序列转换为可连接序列,并通过指定的主题广播其发射。
2.replay
将源可观察序列转换为可连接的序列,并将向每个新订阅服务器重放以前排放的缓冲大小.
首先拥有和publish一样的能力,共享 Observable sequence, 其次使用replay还需要我们传入一个参数(buffer size)来缓存已发送的事件,当有新的订阅者订阅了,会把缓存的事件发送给新的订阅者.
3.push
将源可观察序列转换为可连接序列.共享一个Observable的事件序列,避免创建多个Observable sequence。
注意:需要调用connect之后才会开始发送事件.