小言_互联网的博客

iOS Swfit RxSwift-变化操作符(五)

379人阅读  评论(0)

从本篇开始开始讲解RxSwift的一些操作符(变化操作符、条件和布尔操作符、结合操作符等)。

今天我们主要讲解的就是变化操作符


变化操作符主要包括了8种,分别是Buffer、Window、Map、FlatMap、FlatMapLatest、ConcatMap、Scan、GroupBy

下面我们开始讲解每一个操作符的使用。


1、Buffer 

Buffer 本称为缓冲集合,可以设置制定时间、缓存多少数据,然后发出数据,当然如果不够的也会发出数据。举个例子:


  
  1. func RxSwiftBuffer() {
  2. // buffer 缓冲集合
  3. let subject = PublishSubject< String>()
  4. // 1秒会缓冲3个一起以数组方式抛出。如果缓存不足3个,也会发出。
  5. subject.buffer(timeSpan: 1, count: 3, scheduler: MainScheduler.instance).subscribe(onNext: {
  6. print($ 0)
  7. }).disposed(by: disposeBag)
  8. subject.onNext( "1")
  9. subject.onNext( "2")
  10. subject.onNext( "3")
  11. subject.onNext( "a")
  12. subject.onNext( "b")
  13. subject.onNext( "c")
  14. subject.onNext( "A")
  15. subject.onNext( "B")
  16. }

下面是执行的结果:


  
  1. [ "1", "2", "3"]
  2. [ "a", "b", "c"]
  3. [ "A", "B"]
  4. []
  5. []
  6. []
  7. []
  8. []

从结果可以开出,每隔1秒缓存3个数据,并将数据已集合的方式进行打印,如果数据不满足三条,则打印空集合。

2、Window


window 和 buffer 十分相似。buffer 是周期性的将缓存的元素集合发送出来,window 周期性的将元素集合以 Observable 的形态发送出来。下面举个例子:


  
  1. func RxSwiftWindow() {
  2. // window 和 buffer 十分相似。buffer 是周期性的将缓存的元素集合发送出来,window 周期性的将元素集合以 Observable 的形态发送出来。
  3. // 同时 buffer要等到元素搜集完毕后,才会发出元素序列。而 window 可以实时发出元素序列。
  4. let subject = PublishSubject< String>()
  5. subject.window(timeSpan: 1, count: 3, scheduler: MainScheduler.instance).subscribe(onNext: { [ weak self] in
  6. print( "subscribe: \($0)")
  7. $ 0.asObservable().subscribe(onNext: {
  8. print($ 0)
  9. }).disposed(by: self!.disposeBag)
  10. }).disposed(by: disposeBag)
  11. subject.onNext( "a")
  12. subject.onNext( "b")
  13. subject.onNext( "c")
  14. // print("Resources.total ", RxSwift.Resources.total)
  15. subject.onNext( "1")
  16. // print("Resources.total ", RxSwift.Resources.total)
  17. subject.onNext( "2")
  18. subject.onNext( "3")
  19. // print("Resources.total ", RxSwift.Resources.total)
  20. }

下面是执行结果:


  
  1. subscribe: RxSwift. AddRef< Swift. String>
  2. a
  3. b
  4. c
  5. subscribe: RxSwift. AddRef< Swift. String>
  6. 1
  7. 2
  8. 3
  9. subscribe: RxSwift. AddRef< Swift. String>
  10. subscribe: RxSwift. AddRef< Swift. String>
  11. subscribe: RxSwift. AddRef< Swift. String>
  12. subscribe: RxSwift. AddRef< Swift. String>

从结果可以看出,window通过Observable的方式进行发送,对Observable的内容重新订阅才能拿到具体的内容,当然拿到的内容还是以及集合形式进行打印,如果Observable内容为空将不会获取到集合内容并打印。

3、Map


该操作符通过传入一个函数闭包把原来的 Observable 序列转变为一个新的 Observable 序列。和swift原声的map用法基本一致,下面上代码:


  
  1. func RxSwiftMap() {
  2. // 该操作符通过传入一个函数闭包把原来的 Observable 序列转变为一个新的 Observable 序列。和swift原声的map用法基本一致
  3. // 相当于返回一个10倍的新序列
  4. Observable.of( 1, 2, 3). map { $ 0 * 10 }.subscribe(onNext: {
  5. print($ 0)
  6. }).disposed(by: disposeBag)
  7. }

结果显而易见:


  
  1. 10
  2. 20
  3. 30

4、FlatMap

map 在做转换的时候容易出现“升维”的情况。即转变之后,从一个序列变成了一个序列的序列。

而FlatMap 操作符会对源 Observable 的每一个元素应用一个转换方法,将他们转换成 Observables。 然后将这些 Observables 的元素合并之后再发送出来。即又将其 "拍扁"(降维)成一个 Observable 序列。

这个操作符是非常有用的。比如当 Observable 的元素本生拥有其他的 Observable 时,我们可以将所有子 Observables 的元素发送出来。相当于合并了两个


  
  1. func RxSwiftFlatMap() {
  2. // map 在做转换的时候容易出现“升维”的情况。即转变之后,从一个序列变成了一个序列的序列。
  3. // 而 flatMap 操作符会对源 Observable 的每一个元素应用一个转换方法,将他们转换成 Observables。 然后将这些 Observables 的元素合并之后再发送出来。即又将其 "拍扁"(降维)成一个 Observable 序列。
  4. // 这个操作符是非常有用的。比如当 Observable 的元素本生拥有其他的 Observable 时,我们可以将所有子 Observables 的元素发送出来。
  5. // 相当于合并了两个
  6. let subject1 = BehaviorSubject(value: "A")
  7. let subject2 = BehaviorSubject(value: "1")
  8. let subject3 = BehaviorSubject(value: "中文")
  9. let variable = Variable(subject1)
  10. variable.asObservable().flatMap { $ 0 }.subscribe(onNext: {
  11. print($ 0)
  12. }).disposed(by: disposeBag)
  13. subject1.onNext( "B")
  14. subject1.onNext( "C")
  15. variable.value = subject2 //效果:log:1
  16. subject1.onNext( "D")
  17. subject1.onNext( "E")
  18. variable.value = subject1
  19. subject2.onNext( "3")
  20. subject2.onNext( "4")
  21. variable.value = subject1
  22. subject2.onNext( "3")
  23. subject2.onNext( "4")
  24. // Whenever a new value is set, all the observers are notified of the change.
  25. variable.value = subject3
  26. subject3.onNext( "中文2")
  27. //所以,666依旧会导引出来。此时,subject1、subject2、subject3都是有效的observers
  28. subject2.onNext( "666")
  29. }

  
  1. A
  2. B
  3. C
  4. 1
  5. D
  6. E
  7. E
  8. 3
  9. 4
  10. E
  11. 3
  12. 4
  13. 中文
  14. 中文2
  15. 666

从结果可以看出,每次都会保留上一次的值,但重复值的时候,就会再次打印上一次的值,并且每个subject赋新值的时候也并不会影响其结果。

5、FlatMapLatest


flatMapLatest与flatMap 的唯一区别是:flatMapLatest只会接收最新的value 事件。这样最终就只会输出subject2,subject1就不会输出了


  
  1. func RxSwiftFlatMapLatest() {
  2. // flatMapLatest与flatMap 的唯一区别是:flatMapLatest只会接收最新的value 事件。
  3. // 这样最终就只会输出subject2,subject1就不会输出了
  4. let subject1 = BehaviorSubject(value: "A")
  5. let subject2 = BehaviorSubject(value: "1")
  6. let variable = Variable(subject1)
  7. variable.asObservable().flatMapLatest({ $ 0 }).subscribe(onNext: {
  8. print($ 0)
  9. }).disposed(by: disposeBag)
  10. subject1.onNext( "B")
  11. variable.value = subject2
  12. subject2.onNext( "2")
  13. subject1.onNext( "C")
  14. }

结果:


  
  1. A
  2. B
  3. 1
  4. 2

从结果可以看出,只要赋值新的subject,旧的subject的内容变化便不会再打印结果。

6、ConcatMap


concatMap 与 flatMap 的唯一区别是:当前一个 Observable 元素发送完毕后,后一个Observable 才可以开始发出元素。或者说等待前一个 Observable 产生完成事件后,才对后一个 Observable 进行订阅。

如果subject1不发送onCompleted,subject2永远不会输出


  
  1. func RxSwiftConcatMap() {
  2. // concatMap 与 flatMap 的唯一区别是:当前一个 Observable 元素发送完毕后,后一个Observable 才可以开始发出元素。或者说等待前一个 Observable 产生完成事件后,才对后一个 Observable 进行订阅。
  3. // 如果subject1不发送onCompleted,subject2永远不会输出
  4. let subject1 = BehaviorSubject(value: "A")
  5. let subject2 = BehaviorSubject(value: "1")
  6. let variable = Variable(subject1)
  7. variable.asObservable().concatMap({$ 0}).subscribe(onNext: { print($ 0) }).disposed(by: disposeBag)
  8. subject1.onNext( "B")
  9. variable.value = subject2
  10. subject2.onNext( "2")
  11. subject2.onNext( "C")
  12. subject1.onCompleted() //只有前一个序列结束后,才能接收下一个序列
  13. }

结果:


  
  1. A
  2. B
  3. C

从结果很容易看出,在执行variable.value = subject2的时候,下面的next执行2、C都没有进行打印,只有当subject1.onCompleted()后,才会打印subject2的值,而且subject2的值只会打印最新的一次。

7、Scan


scan 就是先给一个初始化的数,然后不断的拿前一个结果和最新的值进行处理操作。


  
  1. func RxSwiftScan() {
  2. // scan 就是先给一个初始化的数,然后不断的拿前一个结果和最新的值进行处理操作
  3. // 输出为1,3,6,10,15
  4. // acum 为新值 elem为下一个值
  5. Observable.of( 1, 2, 3, 4, 5).scan( 0) { acum, elem in
  6. acum + elem
  7. }.subscribe(onNext: {
  8. print($ 0)
  9. }).disposed(by: disposeBag)
  10. }

结果:


  
  1. 1
  2. 3
  3. 6
  4. 10
  5. 15

8、GroupBy


groupBy 操作符将源 Observable 分解为多个子 Observable,然后将这些子 Observable 发送出来。

也就是说该操作符会将元素通过某个键进行分组,然后将分组后的元素序列以 Observable 的形态发送出来。


  
  1. func RxSwiftGroupBy() {
  2. // groupBy 操作符将源 Observable 分解为多个子 Observable,然后将这些子 Observable 发送出来。
  3. // 也就是说该操作符会将元素通过某个键进行分组,然后将分组后的元素序列以 Observable 的形态发送出来。
  4. // 将奇数偶数分成两组
  5. Observable< Int>.of( 0, 1, 2, 3, 4, 5).groupBy(keySelector: { element in
  6. return element % 2 == 0 ? "偶数" : "奇数"
  7. }).subscribe { (event) in
  8. switch event {
  9. case .next( let group):
  10. group.asObservable().subscribe(onNext: { (event) in
  11. print( "key:\(group.key) event:\(event)")
  12. }).disposed(by: self.disposeBag)
  13. default:
  14. print( "")
  15. }
  16. }.disposed(by: disposeBag)
  17. }

结果:


  
  1. key:偶数 event: 0
  2. key:奇数 event: 1
  3. key:偶数 event: 2
  4. key:奇数 event: 3
  5. key:偶数 event: 4
  6. key:奇数 event: 5

从结果可以看出,groupBy通过间0~5的值先进行了,奇偶书的分组,然后在对分完的内容进行了订阅。


到此操作变化符就介绍完成了,其实在开发过程中使用的频率并不高,但是也有使用的情况,这个看个人需要是要那个操作符。

下面是本人学习过程自己写的一个demo,感兴趣的小伙伴大家可以下载看一看。


Csdn下载

Gitbub下载


转载:https://blog.csdn.net/WangQingLei0307/article/details/116049191
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场