rxSwift

[rxSwift] Transforming Operator 의 종류

웰코발 2022. 10. 23. 15:06

Transforming Operator 의 종류

toArray

  • Observable의 독립적 요소들을 array로 만드는 연산자. (Singe<[T]> 형태로 변환됨)
  • 옵저버블이 방출하는 모든 이벤트를 completed 시점에 배열로 방출함.

let disposeBag = DisposeBag()

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

// [A, B, C]
// completed

let disposeBag = DisposeBag()
let subject = PublishSubject<Int>()
subject
    .toArray()
    .subscribe{ print($0) }
    .disposed(by: disposeBag)

subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
subject.onNext(4)
subject.onNext(5)
subject.onCompleted()

// [1, 2, 3, 4, 5]
// completed

 

map

  • 요소를 원하는 타입의 데이터로 변환해 주는 연산자.
  • 연산을 통해 새로운 Observable 이벤트를 방출함.

let disposeBag = DisposeBag()

Observable.of(Date())
.map { date -> String in
   let dateFormatter = DateFormatter()
   dateFormatter.dateFormate = "yyyy-MM-dd"
   dateFormatter.local = Locale(identifier: "ko_KR")
   return dateFormatter.string(from: date)
 }
.subscribe(onNext: {
   print($0)
 })
.disposed(by: disposeBag)

 

flatMap

  • 각 하나의 sequence에서 각 event에 대해 sequence를 만든 후,
  • 최종적으로 하나의 sequence로 만드는 것.
  • 곧, 모든 sequence들을 통합해서 하나의 sequence로 다루는 것. 
    • 1번 : 01엘리먼트가 flatMap을 만나 새로운 시퀀스 생성, 최종 시퀀스로 전달
    • 2번 : 02엘리먼트가 flatMap을 만나 새로운 시퀀스 생성, 최종 시퀀스로 전달
    • 3번 : 01엘리먼트의 value에 변동이 생김(10 -> 40), 최종 시퀀스로 전달
    • 4번 : 02엘리먼트의 value에 변동이 생김(20 -> 50), 최종 시퀀스로 전달

struct Student {
    var score: BehaviorSubject<Int>
}


let disposeBag = DisposeBag()

let O1 = Student(score: BehaviorSubject(value: 10))
let O2 = Student(score: BehaviorSubject(value: 20))
let O3 = Student(score: BehaviorSubject(value: 30))

let OriginSeq = PublishSubject<Student>()

OriginSeq
    .flatMap{
        $0.score
    }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

OriginSeq.onNext(O1)  // 10

OriginSeq.onNext(O2)  // 20

OriginSeq.onNext(O3)  // 30

O1.score.onNext(40)  // 40

O2.score.onNext(50)  // 50

// 10

// 20

// 30

// 40

// 50

 

flatMapLatest

  • 가장 최근에 만들어진 sequence만 emit
    • 1번 : 01엘리먼트가 flatMap을 만나서 새로운 시퀀스 생성, 최종 시퀀스에 전달
    • 2번 : 동일, 바로 뒤 30은 전달이 안되는 이유는 가장 마지막에 생성된 시퀀스는 20시퀀스이므로 20시퀀스에 대해서만 반응
    • 3번 : 동일, 가장 마지막에 생성된 시퀀스는 40시퀀스이므로 뒤에 60도 최종 시퀀스에 전달 (50은 40시퀀스에 의해 무시)

struct Student {
    var score: BehaviorSubject<Int>
}


let disposeBag = DisposeBag()

let O1 = Student(score: BehaviorSubject(value: 10))
let O2 = Student(score: BehaviorSubject(value: 20))
let O3 = Student(score: BehaviorSubject(value: 40))

let OriginSeq = PublishSubject<Student>()
    
OriginSeq
    .flatMapLatest {
        $0.score
    }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

OriginSeq.onNext(O1)  // 10

OriginSeq.onNext(O2)  // 20

O1.score.onNext(30)   // 무시됨

OriginSeq.onNext(O3)  // 40

O2.score.onNext(50)  // 무시됨

O3.score.onNext(60)  // 60

 

materialize 사용법

  • next이벤트(Int타입)를 Event타입으로 변환
  • onError이벤트를 Event타입으로 변환
  • onCompleted이벤트를 Event타입으로 변환

enum MyError: Error {
    case anError
}

let disposeBag = DisposeBag()

// 2
let O1 = Student(score: BehaviorSubject(value: 80))
let O2 = Student(score: BehaviorSubject(value: 100))

let OriginSeq = BehaviorSubject(value: O1)

OriginSeq
    .flatMapLatest {
        $0.score
    }
    .subscribe(onNext: {
        print($0) 
    })
    .disposed(by: disposeBag)     // 80

O1.score.onNext(85)               // 85
O1.score.onError(MyError.anError) // Unhandled error happened: anError
O1.score.onNext(90)               // none
OriginSeq.onNext(O2)              // none
// 위 코드에 meterialize 적용
enum MyError: Error {
    case anError
}

let disposeBag = DisposeBag()

// 2
let O1 = Student(score: BehaviorSubject(value: 80))
let O2 = Student(score: BehaviorSubject(value: 100))

let OriginSeq = BehaviorSubject(value: O1)

OriginSeq
    .flatMapLatest {
        $0.score.materialize()
    }
    .subscribe(onNext: {
        print($0) 
    })
    .disposed(by: disposeBag)     // 80

O1.score.onNext(85)               // 85
O1.score.onError(MyError.anError) // anError
O1.score.onNext(90)               // 90
OriginSeq.onNext(O2)              // 100