RxSwiftのmapとflatMapの違いを理解できません。 RxSwiftプレイグラウンドの例と本では、内部のObservableプロパティを持つObservableの変換としてflatMapが使用されています。
ただし、基本タイプのObservableで直接使用されているflatMapを確認します。たとえば、以下のコードの場合、どちらも同じ出力を生成します。誰かがマップとflatMapの違いを理解するのを助けてくれますか
struct Student {
let score:Int
}
let ryan = Student(score:80)
let student = PublishSubject<Student>()
let deneme = student.map({ val in
return Student(score: val.score+10)
})
deneme.subscribe(onNext: {
print("StudentMAP: \($0.score)")
})
let deneme2 = student.flatMap({ val -> Observable<Student> in
return Observable.of(Student(score: val.score + 10))
})
deneme2.subscribe(onNext: {
print("StudentFlatMAP: \($0.score)")
})
student.onNext(ryan)
flatMapはmapに似ていますが、オブザーバブルの要素をシーケンスの観察可能。使用する例は比較的単純で、単にObservableを送信し、別のものにマッピングします。
ここ は、Reactive拡張ドキュメントからの引用です。
FlatMapオペレーターは、ソースObservableによって発行された各アイテムに指定した関数を適用することによってObservableを変換します。この関数は、それ自体がアイテムを発行したObservableを返します。次に、FlatMapは、これらの結果のObservableの放出をマージし、これらのマージされた結果を独自のシーケンスとして放出します。
このメソッドは、たとえば、それ自体がObservableメンバーを持っている、または他の方法でObservableに変換可能な一連のアイテムを発行するObservableがある場合に役立ちます。これにより、これらのアイテムのサブオブザーバブル。
この例を少し拡張すると、flatMapが実際に各要素をシーケンスに変換することがわかります。
あなたが使用したことに注意してください、
student.onNext(ryan)
Dename2を削除し、このコードを下に追加します。
let studentObservable: PublishSubject<Student> = PublishSubject()
let deneme2 = student.flatMap({ val -> Observable<Student> in
return studentObservable.map { val in Student(score: val.score + 10) }
})
deneme2.subscribe(onNext: {
print("StudentFlatMAP: \($0.score)")
})
student.onNext(ryan)
studentObservable.onNext(Student(score: 80))
studentObservable.onNext(Student(score: 90))
studentObservable.onNext(Student(score: 100))
これで、mapが単純にシーケンスから値を変換し、新しいObservableが作成され、flatMapがそれをシーケンスに変換します。現在、それぞれのflatMapped要素は、それ自体がストリームであるため、値を生成できます。
mapストリームから値を取得し、任意のタイプの別の値を返します。結果はObservable <どんなタイプ>です。
flatMapストリームから値を取得し、Observableを返すあらゆるタイプの値を取得します。
これは、次の場合にflatMapを使用できることを意味します。
observable <を返す関数がすでに宣言されていますか? >、flatMapで使用することをお勧めします
func foo(_ number: Int) -> Observable<String> {
return Observable.just(String(number))
}
Observable.just(1)
.flatMap { (number) -> Observable<String> in
return foo(number)
}
ストリームに複数の値をプッシュする戻り値が必要です
func updates() -> Observable<String> {
// Something that generates updates
}
func shouldListenToUpdated() -> Observable<Bool> {
return Observable.just(true)
}
shouldListenToUpdated()
.flatMap { (listenToUpdated) -> Observable<String> in
return listenToUpdated ? updates() : Observable.empty()
}
一方、マップはストリームの次の値を変換するだけです。
これで状況が少し明確になることを願っています。
シンプルに保つには、ストリームのObservableを返したいときにflatMapを使用します。マップの使用は、オブザーバブルの値を変換してストリームを渡すだけです
フラットマップ:
response.flatMap { response, _ -> Observable<NSString> in
guard let value = response.allHeaderFields["string"] as? NSString
else {
return Observable.empty()
}
return Observable.just(value)
}.subscribe(onNext: { [weak self] string in
print(string)
}).disposed(by: bag)
地図:
response.filter { response, _ in
return 200..<300 ~= response.statusCode
}.map { _ , data -> [[String: Any]] in
guard let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
let result = jsonObject as? [[String: Any]] else {
return []
}
return result
}.subscribe(onNext: { [weak self] objects in
print(objects)
}).disposed(by: bag)