1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RxSwift Transforming Operators

Last updated at Posted at 2020-11-24

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)

コンパイル結果
Screen Shot 2020-11-24 at 3.16.47 PM.png

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)

コンパイル結果
Screen Shot 2020-11-24 at 3.18.30 PM.png

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)

コンパイル結果
Screen Shot 2020-11-24 at 3.20.46 PM.png

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)

コンパイル結果
Screen Shot 2020-11-24 at 3.22.18 PM.png

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)

コンパイル結果
Screen Shot 2020-11-24 at 3.22.40 PM.png

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)

コンパイル結果
Screen Shot 2020-11-24 at 3.22.55 PM.png

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)

コンパイル結果
Screen Shot 2020-11-24 at 3.23.10 PM.png

参考文献

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/

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?