RxSwift 高阶函数
今天我们来探索下RxSwift
高阶函数,和一些组合函数的用法
组合操作符
startWith()
- 在开始从可观察源发出元素之前,发出指定的元素序列
elements
:要附加到指定序列的元素returns
: 返回以指定值开头的源序列
public func startWith(_ elements: Self.E...) -> RxSwift.Observable<Self.E>
Observable<String>.of("1","2","3")
.startWith("a")
.startWith("b")
.subscribe(onNext: { (element) in
Log(element)
}).disposed(by: self.disposeBag)
//打印值 : b a 1 2 3
merge()
- 将源可观察序列中的元素组合成一个新的可观察序列,并将像每个源可观察序列发出元素一样发出每个元素
maxConcurrent
:同时订阅的内部可观察序列的最大数量returns
:返回 合并内部序列元素的可观察序列
public func merge(maxConcurrent: Int) -> RxSwift.Observable<Self.E.E>
使用例子:
print("*****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("J")
subject1.onNext("a")
subject2.onNext("d")
// 打印
// J
// a
// d
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
let subject3 = PublishSubject<String>()
let subject4 = PublishSubject<String>()
// merge subject1和subject2
Observable.of(subject1, subject2,subject3,subject4)
.merge(maxConcurrent: 2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("J")
subject1.onNext("a")
subject2.onNext("d")
subject2.onNext("e")
subject3.onNext("k")
subject4.onNext("i")
//打印
// J
// a
// d
// e
当
maxConcurrent
设置为2
的时候,我们发现subject3
和subject4
的数据打印不出来,以此证明maxConcurrent
这个参数限制的是观察者序列的个数,而不是总的赋值个数
,
zip()
- 将多达8个源可观测序列组合成一个新的可观测序列,并将从组合的可观测序列中发射出对应索引处每个源可观测序列的元素
- 说白了: 只有两个序列同时有值的时候才会响应,否则存值
source1、source2
: 元素resultSelector
: 在源中的相应索引处调用每个元素系列的函数returns
:可观察的序列,包含使用指定的结果选择器功能合并源元素的结果
public static func zip<O1, O2>(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> Self.E) -> RxSwift.Observable<Self.E> where O1 : RxSwift.ObservableType, O2 : RxSwift.ObservableType
使用例子:
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("C")
stringSubject.onNext("o") // 到这里存储了 C o 但是不会响应除非;另一个响应
// print nil
intSubject.onNext(1) // 勾出一个
// print C 1
intSubject.onNext(2) // 勾出另一个
/*
print
C 1
o 2
*/
stringSubject.onNext("i") // 存一个
/*
print
C 1
o 2
*/
intSubject.onNext(3) // 勾出一个
/*
print
C 1
o 2
i 3
*/
// 说白了: 只有两个序列同时有值的时候才会响应,否则存值
combineLatest()
- 每当任何可观察序列产生一个元素时,通过使用选择器功能将指定的可观察序列合并为一个可观察序列
source1、source2
: 元素resultSelector
: 每当任何源产生元素时要调用的函数数returns
:可观察的序列,包含使用指定的结果选择器功能合并源元素的结果- 应用非常频繁: 比如账户和密码同时满足->才能登陆. 不关系账户密码怎么变化的只要查看最后有值就可以 loginEnable
public static func combineLatest<O1, O2>(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> Self.E) -> RxSwift.Observable<Self.E> where O1 : RxSwift.ObservableType, O2 : RxSwift.ObservableType
使用例子:
let stringSub = PublishSubject<String>()
let intSub = PublishSubject<Int>()
Observable.combineLatest(stringSub, intSub) { strElement, intElement in
"\(strElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
stringSub.onNext("L") // 存一个 L
stringSub.onNext("G") // 存了一个覆盖 - 和zip不一样
// print nil
intSub.onNext(1) // 发现intSub也有G 响应 G 1
// print G 1
intSub.onNext(2) // 覆盖1 -> 2 发现intSub 有值G 响应 G 2
// print G 2
stringSub.onNext("Jadekirin") // 覆盖G -> Jadakirin 发现intSub 有值2 响应 Jadekirin 2
// print Jadekirin 2
//
combineLatest
相比zip
会覆盖
switchLatest()
- 将可观察序列发出的元素转换为可观察序列,并从最近的内部可观察序列发出元素
public func switchLatest() -> RxSwift.Observable<Self.E.E>
使用例子:
let switchLatestSub1 = BehaviorSubject(value: "L")
let switchLatestSub2 = BehaviorSubject(value: "1")
let switchLatestSub = BehaviorSubject(value: switchLatestSub1)// 选择了 switchLatestSub1 就不会监听 switchLatestSub2
switchLatestSub.asObservable()
.switchLatest()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
switchLatestSub1.onNext("T")
switchLatestSub1.onNext("B")
switchLatestSub2.onNext("2")
switchLatestSub2.onNext("3") // 2-3都会不会监听,但是默认保存由 2覆盖1 3覆盖2
// print L T B
switchLatestSub.onNext(switchLatestSub2) // 切换到 switchLatestSub2
switchLatestSub1.onNext("*") // 不会被打印
// Print L T B 3
switchLatestSub1.onNext("H") // 不会被打印但是 H 会覆盖 * 原理同上面 下面如果再次切换到 switchLatestSub1会打印出 H
switchLatestSub2.onNext("4")
// Print L T B 3 4
switchLatestSub.onNext(switchLatestSub1)
// Print L T B 3 4 H
变换操作符
map()
- 转换闭包应用于可观察序列发出的元素,并返回转换后的元素的新可观察序列
transform
: 应用于每个源元素的转换函returns
: 一个可观察的序列,其元素是调用源的每个元素上的转换函数的结果
public func map<R>(_ transform: @escaping (Self.E) throws -> R) -> RxSwift.Observable<R>
使用例子:
let _ = Observable.of(1,2,3,4)
.map { $0 + 1 }
.subscribe { Log($0) }
.disposed(by: self.disposeBag)
// 2 3 4 5
flatMap() and flatMapLatest()
- 将可观测序列发射的元素转换为可观测序列,并将两个可观测序列的发射合并为一个可观测序列。
- 这个操作符是非常有用的。比如当
Observable
的元素本生拥有其他的Observable
时,我们可以将所有子Observables
的元素发送出来。 - 这也很有用,例如,当你有一个可观察的序列,它本身发出可观察的序列,你想能够对任何一个可观察序列的新发射做出反应(序列中序列:比如网络序列中还有模型序列)
flatMap
和flatMapLatest
的区别是,flatMapLatest
只会从最近的内部可观测序列发射元素,也就是最新的序列元素flatMapLatest
实际上是map
和switchLatest
操作符的组合
public func flatMap<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : RxSwift.ObservableConvertibleType
public func flatMapLatest<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : RxSwift.ObservableConvertibleType
使用例子:
let boy = BehaviorSubject(value: "10")
let girl = BehaviorSubject(value: "A")
let player = BehaviorSubject(value: boy)
player.asObservable()
.flatMap { $0 } // 本身score就是序列 模型就是序列中的序列
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
boy.onNext("60")
player.onNext(girl)
girl.onNext("B")
boy.onNext("50")
// 10 60 A B
// 换成 flatMapLatest
player.asObservable()
.flatMapLatest { $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
boy.onNext("60")
player.onNext(girl)
girl.onNext("B")
boy.onNext("50")
boy.onNext("40")// 如果切换到 flatMapLatest 就不会打印
girl.onNext("C")
// 10 60 A B C
我们发现用
flatMapLatest
的时候,40 、50
就不打印了。
这就说明flatMapLatest
只会从最近的内部可观测序列发射元素,就是说切换到girl
以后就会舍弃boy
concatMap()
- 将可观测序列的每个元素编程到可观测序列中,并将生成的可观测序列串联到一个可观测序列中
concatMap
与flatMap
的唯一区别是:当前一个Observable
元素发送完毕后,后一个Observable
才可以开始发出元素。或者说等待前一个Observable
产生完成事件后,才对后一个Observable
进行订阅
public func concatMap<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : RxSwift.ObservableConvertibleType
使用例子:
let subject1 = BehaviorSubject(value: "A")
let subject2 = BehaviorSubject(value: "1")
let variable = Variable(subject1)
variable.asObservable()
.concatMap { $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("B")
variable.value = subject2
subject2.onNext("2")
subject1.onNext("C")
subject1.onCompleted()
// A B C 2
只有
subject1
执行完以后subject2
才开始执行
buffer()
- 该方法简单来说就是缓存
Observable
中发出的新元素,当元素达到某个数量,或者经过了特定的时间,它就会将这个元素集合发送出来 timeSpan
:缓冲区的最大时间长度count
:缓冲区的最大元素计数scheduler
:计划程序运行缓冲计时器returns
:可观察到的缓冲区序列
public func buffer(timeSpan: RxSwift.RxTimeInterval, count: Int, scheduler: RxSwift.SchedulerType) -> RxSwift.Observable<[Self.E]>
使用例子:
let subject = PublishSubject<String>()
//每缓存3个元素则组合起来一起发出。
//如果1秒钟内不够3个也会发出(有几个发几个,一个都没有发空数组 [])
subject
.buffer(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject.onNext("a")
subject.onNext("b")
subject.onNext("c")
subject.onNext("1")
subject.onNext("2")
/*
["a", "b", "c"]
["1", "2"]
[]
[]
*/
scan()
- 从初始就带有一个默认值开始,然后对可观察序列发出的每个元素应用累加器闭包,并以单个元素可观察序列的形式返回每个中间结果
- 这里主要强调序列值之间的关系
seed
: 初始值accumulator
: 要在每个元素上调用的累加器函数returns
: 包含累积值的可观察序列
public func scan<A>(_ seed: A, accumulator: @escaping (A, Self.E) throws -> A) -> RxSwift.Observable<A>
使用例子:
Observable.of(1,3,5)
.scan(4) { (aggre, newValue) in
aggre + newValue
}
.subscribe({Log($0)})
.disposed(by: self.disposeBag)
//4+1 5
//4+1+3 8
//4+1+3+5 13
过滤条件操作符
filter()
- 仅满足指定条件的可观察序列中发出那些元素
predicate
:用于测试每个源元素的条件的函数。returns
:包含满足条件的输入序列中的元素的可观察序列
public func filter(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
使用例子:
Observable.of(1,3,4,5,23,46)
.filter({$0 % 2 == 0})
.subscribe(onNext: {Log($0)})
.disposed(by: self.disposeBag)
//print 4 46
distinctUntilChanged()
- 过滤可观察序列发出的顺序(连续)重复的元素
public func distinctUntilChanged() -> RxSwift.Observable<Self.E>
使用例子:
Observable.of(1,2,2,3,3,4,3,3,5,4,5)
.distinctUntilChanged()
.subscribe(onNext: {Log($0)})
.disposed(by: self.disposeBag)
// 1 2 3 4 3 5 4 5
elementAt()
- 仅在可观察序列发出的所有元素的指定索引处发出元素
(就是打印出指定索引的元素)
index
: 所需元素的索引(从 0 开始)returns
: 将所需元素作为其唯一发射物发出的可观测序列
public func elementAt(_ index: Int) -> RxSwift.Observable<Self.E>
Observable.of(10,20,30,50)
.elementAt(3)
.subscribe(onNext: {Log($0)})
.disposed(by: self.disposeBag)
// 50
single()
- 只发出可观察序列发出的第一个元素(或满足条件的第一个元素)。
- 如果可观察序列发出多个元素,将抛出一个错误。
public func single() -> RxSwift.Observable<Self.E>
Observable.of("C", "K")
.single{ $0 == "K"}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// K
Observable.of("C", "K")
.single()
.subscribe(onNext: { print($0) }) //发出的第一个元素
.disposed(by: disposeBag)
// C
Observable.of("J", "H","G")
.single { $0 == "H" || $0 == "J" }
.subscribe(onNext: {Log($0)}, onError: { (error) in
Log("报错--\(error)")
})
.disposed(by: disposeBag)
// J 满足条件的第一个元素
// 报错--Sequence contains more than one element.
take()
- 只从一个可观察序列的开始发出指定数量的元素(最前面的元素)。
- 在满足数量之后会自动
.completed
count
: 要返回的元素数
public func take(_ count: Int) -> RxSwift.Observable<Self.E>
Observable.of("H", "K","C", "L")
.take(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// H K
takeLast()
- 仅从可观察序列的末尾发出指定数量的元素
count
: 要从源序列末尾执行的元素数。
public func takeLast(_ count: Int) -> RxSwift.Observable<Self.E>
Observable.of("H", "K","C", "L")
.takeLast(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// C L
takeWhile()
- 只要指定条件的值为
true
,就从可观察序列的开始发出元素 predicate
:用于测试每个元素的条件的函数
public func takeWhile(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
Observable.of(1,2,3,4,5,6,7,8)
.takeWhile({$0 < 4})
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// 1 2 3
takeUntil()
- 从源可观察序列发出元素,直到参考可观察序列发出元素
- 这个比较重点,应用非常频繁 比如我页面销毁了,就不能获取值了(cell重用运用)
other
:终止源序列元素传播的可观察序列。returns
:包含源序列元素的可观察序列,一个到其他序列中断进一步传播的点
public func takeUntil<O>(_ other: O) -> RxSwift.Observable<Self.E> where O : RxSwift.ObservableType
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.takeUntil(referenceSequence)
.subscribe { print($0) }
.disposed(by: disposeBag)
sourceSequence.onNext("A")
sourceSequence.onNext("K")
sourceSequence.onNext("C")
referenceSequence.onNext("H") // 条件一出来,下面就走不了
sourceSequence.onNext("L")
// A K C completed
referenceSequence
条件已执行,就不会往下执行了
Skip()
- 从源可观察序列发出元素,直到参考可观察序列发出元素
- 应用非常频繁 不用解释 textfiled 都会有默认序列产生
- 输出不符合条件的元素
- 和take相反
count
: 返回其余元素之前要跳过的元素数
public func skip(_ count: Int) -> RxSwift.Observable<Self.E>
Observable.of(1, 2, 3, 4, 5, 6)
.skip(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// 3 4 5 6
skipWhile()
- 只要指定条件的值为
false
,就从可观察序列的开始发出元素 predicate
:用于测试每个元素的条件的函数- 和
takeWhile
相反
public func skipWhile(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
Observable.of(1, 2, 3, 4, 5, 6)
.skipWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// 4 5 6
skipUntil()
- 抑制从源可观察序列发出元素,直到参考可观察序列发出元素
- 和
takeUntil
相反 other
:开始传播源序列元素的可观察序列。
public func skipUntil<O>(_ other: O) -> RxSwift.Observable<Self.E> where O : RxSwift.ObservableType
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.skipUntil(referenceSequence)
.subscribe { print($0) }
.disposed(by: disposeBag)
sourceSequence.onNext("A")
sourceSequence.onNext("K")
sourceSequence.onNext("C")
referenceSequence.onNext("H") // 条件一出来,下面就开始了
sourceSequence.onNext("L")
//print L
ignoreElements()
- 该操作符可以忽略掉所有的元素,只发出
error
或completed
事件 - 如果我们并不关心
Observable
的任何元素,只想知道Observable
在什么时候终止,那就可以使用ignoreElements
操作符。
Observable.of(1, 2, 3, 4)
.ignoreElements()
.subscribe{
print($0)
}disposed(by: disposeBag)
// completed
还有很多高阶函数,后续会再行探索