Transforming Operatorsまとめ
RxSwiftでコードを書く必要があり、学習中です。
参考文献を元に学んだ内容をすぐ振り返れるようにまとめていきます。
今回はTransforming Operatorsについてまとめました。
完全に自分の解釈でコメントを載せていますが、解釈に誤りがありましたら、コメント欄より教えてください。
toArray()
Observableから発火されたelementをArrayに詰め込んでSingleで返す。
import Foundation
import RxSwift
let disposeBag = DisposeBag()
// 1
Observable.of("A", "B", "C")
// 2
.toArray()
.subscribe(onSuccess: {
print($0)
})
.disposed(by: disposeBag)
map()
標準と一緒。各値に処理を加えて返す。ただし、nilが含まれる可能性がある場合はOptionalを返す。
let disposeBag = DisposeBag()
// 1
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
// 2
Observable<Int>.of(123, 4, 56)
// 3
.map {
formatter.string(for: $0) ?? ""
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
enimerated()
Observableから受け取った値にindexを振り管理できる。
let disposeBag = DisposeBag()
// 1
Observable.of(1, 2, 3, 4, 5, 6)
// 2
.enumerated()
// 3
.map { index, integer in
index > 2 ? integer * 2 : integer
}
// 4
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
compactMap()
map+nilを取り除くfilter: オプショナルをアンラップして、nilがある場合、nilを破棄。
let disposeBag = DisposeBag()
// 1
Observable.of("To", "be", nil, "or", "not", "to", "be", nil)
// 2
.compactMap { $0 }
// 3
.toArray()
// 4
.map { $0.joined(separator: " ") }
// 5
.subscribe(onSuccess: {
print($0)
})
.disposed(by: disposeBag)
flatMap()
後述のflatMap()と異なり、Observableが変わっても、継続して以前のObservableから値を受け取り続ける。
map()だと返り値は以下の となる。
RxSwift.BehaviorSubject
flatMap()することで、Array(s.map(transform).joined()).と同等の処理がされるため、
Array >をArrayにすることができる。
struct Student {
let score: BehaviorSubject<Int>
}
let disposeBag = DisposeBag()
// 1
let laura = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 90))
// 2
let student = PublishSubject<Student>()
// 3
student
.flatMap {
$0.score
}
// 4
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
student.onNext(laura)
laura.score.onNext(85)
student.onNext(charlotte)
laura.score.onNext(95)
charlotte.score.onNext(100)
flatMapLatest()
Map + switchLatest: Observableが変わったら最新のObservableからのみ値を受け取り、前のObservableからは値を受け取らない。
let disposeBag = DisposeBag()
let laura = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 90))
let student = PublishSubject<Student>()
student
.flatMapLatest {
$0.score
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
student.onNext(laura)
laura.score.onNext(85)
student.onNext(charlotte)
// 1
laura.score.onNext(95)
charlotte.score.onNext(100)
materialize() && dematerialize()
materialize()しない場合、エラーが起こったとき、そこでdisposeされてしまうが、materialize()することでelementをeventに変換し、.dematerialize()でelementに戻すことで、エラーが起こったObservableはUnsubscribeされるが、別のObservableは継続して使用することができる。
// 1
enum MyError: Error {
case anError
}
let disposeBag = DisposeBag()
// 2
let laura = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 100))
let student = BehaviorSubject(value: laura)
// 1
let studentScore = student
.flatMapLatest {
$0.score.materialize()
}
// 2
studentScore
// 1
.filter {
guard $0.error == nil else {
print($0.error!)
return false
}
return true
}
// 2
.dematerialize()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 3
laura.score.onNext(85)
laura.score.onError(MyError.anError)
laura.score.onNext(90)
// 4
student.onNext(charlotte)
参考文献
1.RxSwift: Reactive Programming with Swift
Chapter7 Transforming Operators Written by Scott Gardner
詳細が気になる方はこちらをご参照ください!
https://www.raywenderlich.com/13285844-rxswift-reactive-programming-with-swift-update-now-available
2.https://www.swiftbysundell.com/basics/map-flatmap-and-compactmap/
3.https://www.avanderlee.com/swift/compactmap-flatmap-differences-explained/
4.https://academy.realm.io/jp/posts/try-swift-soroush-khanlou-sequence-collection/