一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
本文主要介绍在RxSwift中映射操作map原理解析, 关于swift中的map可以看下之前的文章 swift的数组Swift中高阶函数的使用。本质上来说就是通过便利进行trasform
转换,得到一个新的结构。
1. map
我们先看下我们使用RxSwift把我们数组里的元素转换为字符串类型
let disposeBag = DisposeBag()
let ob = Observable.from([1,2,3])
ob.map{"\($0)"}
.subscribe(onNext: {print($0.description)})
.disposed(by:disposeBag )//打印结果字符串1,2,3
复制代码
我们看下里面的实现,点击查看map
它是可观察序列协议的拓展,定义了一个map
的方法。这样我们的可观察序列都具备了map的方法,该方法最后返回一个可观察序列
。继续点击查看Map(source: self.asObservable(), transform: transform)
Map
类初始化保存了源序列喝我们map的闭包transform
。此时Map类也是继承于Producer
因此具有subscribe
的能力。这里流程和之前分析一样,在订阅的时候会进入Producer的subscribe
方法
第一次进入需要进行绑定线程的调度环境
,关于调度后面的文章会进行分析。这里会走序列的run方法,我们的Map.run
这里穿入的观察者就是我们订阅的时候创建的匿名观察者AnonymousObserver
,之前文章有分析过核心逻辑。
继续查看
正常我们这里会执行sink.run
,但是这里游再次通过源可观察序列进行subscribe
订阅。这里会走我们之前分析的订阅流程
我们的源序列是通过便捷方法from
创建的,因此源可观察序列为ObservableSequence
类型
因此我们查看ObservableSequence
的run
方法
通过管子sink关联观察者和序列,observer
为我们保存transform闭包
的MapSink
,查看管子的run方法。
可以发现里面有个迭代器,这里的parent为我们开始时时候源序列,我们继续走 forwardOn
这里的observer为mapsink
因此我们去查看mapSink
的on方法
这里会把我们保存的transform
闭包进行调用,之后在进行forwardOn
事件。
进入父类sink的forwardOn
方法,此时next事件中我们的元素从Int类型转换成了string类型
。此时我们的observer为我们订阅的时候创建的匿名观察者
进入序列的onCore
方法
最后调用匿名观察者的事件闭包
2. flatMap
flatMap在Swift的高阶函数是
可以看到flatMap
是把数组中的数组进行了压平的操作,相当于二维数组转换为一维的数组
。 那么在RxSwift中时如何呢?
flatMap 操作符将源 Observable
的每一个信号应用一个转换方法,将他们转换成 Observables
。 然后将这些 Observables
的信号合并之后再发送出来。
//结构体
struct Player {
let score: BehaviorRelay<Int>
init(score:Int) {
self.score = BehaviorRelay(value: score)
}
}
let playerA = Player.init(score: 20)
let playerB = Player.init(score: 30)
let player = BehaviorRelay(value: playerA)
player.asObservable()
.flatMap { (player:Player) ->Observable<Int> in
player.score.asObservable()
}.subscribe { (num) in
print(num)
} onError: { (error) in
print(error)
} onCompleted: {
print("completed")
} onDisposed: {
print("disposed")
}.disposed(by: disposBag)
playerA.score.accept(40)
playerB.score.accept(50)
player.accept(playerB)
playerB.score.accept(60)
playerA.score.accept(70)
复制代码
我们看下它的核心逻辑
保存我们的源序列和我们flatMap
转换的闭包
(该闭包返回的是一个可观察序列)。 同样的我们订阅的时候会进入run方法,因为我们的FlatMapSink
继承于MergeSink
因此sink.run会进入mergeSink
的run方法中
我们的源序列进行订阅传入的是我们的FlatMapSink
,这里会走我们soucre序列
的订阅方法,此时我们的序列为BehaviorRelay
这里结合你自身源序列的类型,走对应的subscribe
方法。我们的FlatMapSink
没有on方法
,我们去它的父类查找。
这里就是核心
这里是调用子类的performMap
,也就是FlatMapSink
的具体实现返回一个新的可观察序列
进行内部订阅
之后新的序列进行事件发送
进行回调。
3. 总结
对于映射操作Map我们,这里就介绍这2种,具体情况还是要自己打断点分析分析。
- map
其实来说就是对于我们的可观察序列的元素element
是数组的时候,我们通过map保存了一个闭包
,当发送信号的时候,会经过一层transform
闭包的回调处理我们的发送元素element
,之后进行eventHanlde
到订阅者的回调。
- Flatmap
对于FlatMap
其实我们从底层来说也是类似,我们不再转换元素而是转换了序列源,我们的序列相当一个中间层
,当源序列发生改变,我们的订阅的内容也随之发生改变,相当于一个转接头
。