RxSwfit 学习笔记(六)转换操作符map、flatMap、flatMapLatest、concatMap等

4,173 阅读4分钟

转换操作符

map

通过一个转换函数,将 Observable 的每个元素转换一遍

案例

class SixthViewController: UIViewController {

    let disposeBag = DisposeBag()
    override func viewDidLoad() {
        super.viewDidLoad()

        let arr:[Dictionary<String,Any>] = [
            ["name":"张三","age":23],
            ["name":"李四","age":33],
            ["name":"王五","age":22],]
        
        Observable.from(arr)
            .map { Person.init(dic: $0) }
            .subscribe(onNext: { print($0.name!) })
            .disposed(by: disposeBag)
        
    }
    
    struct Person {
        var name:String!
        var age:Int!
        init(dic:Dictionary<String,Any>) {
            self.name = dic["name"] as? String
            self.age = dic["age"] as? Int
        }
    }
}

flatMap

Observable 的元素转换成其他的 Observable,然后将这些Observables 合并。
Observable的元素转换成其他的Observable。(如:案例中C的元素是A) flatMap 操作符将源 Observable的每一个元素应用一个转换方法,将他们转换成Observables。 然后将这些 Observables的元素合并之后再发送出来。

这个操作符是非常有用的,例如,当 Observable的元素本身拥有其他的Observable时,你可以将所有子Observables 的元素发送出来。

官方案例

在学的过程,我看《RxSwift中文文档》里面的案例很难受,啪啪啪打脸啊。
案例中他用了Variable,可是在前面他自己又提到了Variable已经弃用了,然后我看着这个案例我就很难受,觉得这对一名新手来说非常不友好。那怎么办呢?

我想我会照成困扰的原因还是在于这句话。
将 Observable的元素转换成其他的 Observable,然后将这些Observables合并

合并是什么意思?
我发现我跳过了很重要的一部分,就是合并,本来这篇文章是比第五篇出来得早的,但是我觉得并没有理解它,还是仔细把第五篇补上。学习顺序还是很重要的!
所以看到这里的如果没看过第五篇还是去看一下。

稍微理清楚了,这里我想了一个比方,可能不太准确。

这个理解起来真的非常的恶心,想了半天想了这么一个例子。

C是一个领班,A和B是工人,领班通过 flatMap把A和B招进来,然后当AB工作时(onNext),领班就能知道A和B都做了什么。

案例

let A = BehaviorSubject(value: "A的默认消息")
let B = BehaviorSubject(value: "B的默认消息")

Observable.of(A,B)//同时观察了A,B
.flatMap {$0} //将Observable的元素转换成其他的Observable",把对 A/B 的观察" 转成 "A/B 观察的字符串"
.subscribe(onNext: {print($0)})
.disposed(by: disposeBag)

A.onNext("A-2")
A.onNext("A-3")
B.onNext("B-2")
B.onNext("B-3")
B.onNext("B-4")

打印结果

A的默认消息
B的默认消息
A-2
A-3
B-2
B-3
B-4

flatMapLatest

Observable 的元素转换成其他的Observable,然后取这些 Observables中最新的一个。 flatMapLatest操作符将源Observable 的每一个元素应用一个转换方法,将他们转换成Observables。一旦转换出一个新的 Observable,就只发出它的元素,旧的 Observables的元素将被忽略掉。

理解了flatMap之后再来理解这个flatMapLatest就比较容易了

A比B先进工厂 ,在B还没进工厂前,领班C需要看着A。B进工厂后,领班觉得A做得熟练了,就不管A了,只看着B。

案例 跟flatMap 的案例只是换了一下单词flatMapLatest

let A = BehaviorSubject(value: "A的默认消息")
let B = BehaviorSubject(value: "B的默认消息")

Observable.of(A,B)
.flatMapLatest {$0}
.subscribe(onNext: {print($0)})
.disposed(by: disposeBag)

A.onNext("A-2")
A.onNext("A-3")
B.onNext("B-2")
B.onNext("B-3")
B.onNext("B-4")

打印结果

A的默认消息
B的默认消息
B-2
B-3
B-4

当观察者从A转到B的时候,就不再观察A发出来的元素。

concatMap

将 Observable 的元素转换成其他的 Observable,然后将这些 Observables 串连起来

concatMap操作符将源 Observable 的每一个元素应用一个转换方法,将他们转换成 Observables。然后让这些Observables 按顺序的发出元素,当前一个 Observable 元素发送onCompleted()后,后一个 Observable 才可以开始发出元素。等待前一个Observable 产生完成事件后,才对后一个 Observable 进行订阅。

在第一个Observable 元素onCompleted()后,第二个Observable 元素可以发出第一个结束前发出的最后一个onNext()

案例 这个案例跟上两个的区别是多了一个onCompleted()

let A = BehaviorSubject(value: "A的默认消息")
let B = BehaviorSubject(value: "B的默认消息")

Observable.of(A,B)
.concatMap {$0}
.subscribe(onNext: {print($0)})
.disposed(by: disposeBag)

A.onNext("A-2")
B.onNext("B-2")
B.onNext("B-3")
A.onCompleted()
A.onNext("A-3")
B.onNext("B-4")


打印结果

A的默认消息
A-2
B-3
B-4

一旦A发出onCompleted(),会发出B先前发出的最后一个元素。

scan

持续的将Observable的每一个元素应用一个函数,然后发出每一次函数返回的结果。

scan操作符将对第一个元素应用一个函数,将结果作为第一个元素发出。然后,将结果作为参数填入到第二个元素的应用函数中,创建第二个元素。以此类推,直到遍历完全部的元素。

案例

        let disposeBag = DisposeBag()

        Observable.of(10, 100, 1000)
            .scan(0) { aValue, newValue in
                aValue + newValue
            }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

打印结果

10
110
1110