최근에 공부를 못하고 . . 프젝이랑 코테 CS만 하다 . . 다시 정신차립니다 . .
빠르게 남은 파트 정리하고 다른 공부도 해야죠 ! 하하
Transforming elements
toArray

Observable의 독립적인 요소들을 array로 넣는 방법
[코드]
example(of: "toArray") {
let disposeBag = DisposeBag()
// 1
Observable.of("A", "B", "C")
// 2
.toArray()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
/* Prints:
["A", "B", "C"]
*/
}
map

표준 라이브러리 map과 같이 사용되며 Observable에서 동작합니다.
enumerated
example(of: "enumerated and map") {
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)
}
/*
--- Example of: enumerated and map ---
1
2
3
8
10
12
*/
compactMap
nil을 제거하고 옵셔널 바인딩해주는 Swift 표준라이브러리 compactMap과 같이 동작합니다.
[코드]
example(of: "compactMap") {
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)
}
/*
--- Example of: compactMap ---
To be or not to be
*/
Transforming inner observables
flatMap
flatMap을 "Observable sequence의 각 요소를 Observable sequence에 투영하고 Observable sequence를 Observable sequence로 병합합니다."라고 정의하고 있습니다.
뭔 뜻일까 . . ?

[코드]
example(of: "flatMap") {
let disposeBag = DisposeBag()
// 1
let ryan = 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)
// 5
student.onNext(ryan) // Printed: 80
// 6
ryan.score.onNext(85) // Printed: 80 85
// 7
student.onNext(charlotte) // Printed: 80 85 90
// 8
ryan.score.onNext(95) // Printed: 80 85 90 95
// 9
charlotte.score.onNext(100) // Printed: 80 85 90 95 100
}
즉, flatMap은 각 Observable의 변화를 계속 지켜봅니다.
flatMapLatest
flatMap에서 가장 최신의 값만 확인하고 싶을 때, flatMapLatest를 사용합니다.
flapMapLatest = map + switchLatest (switchLastest에 대해선 나중에 다뤄볼게요 . . !)

[코드]
example(of: "flatMapLatest") {
let disposeBag = DisposeBag()
let ryan = 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(ryan)
ryan.score.onNext(85)
student.onNext(charlotte)
// 1
ryan.score.onNext(95)
charlotte.score.onNext(100)
/* Prints:
80 85 90 100
*/
}
ryan.score.onNext(95)가 반영되지 않았습니다.
그 이유는 flatMapLatest가 이미 가장 최근 Observable인 charlotte로 전환했기 때문입니다.
언제 사용할까 ?
네트워킹 조작에서 가장 흔하게 쓰일 수 있습니다.
사전으로 단어를 찾는 경우를 생각해봅시다.
s, w, i, f, t를 입력하면 새 검색을 실행하고, 이전 검색(s, sw, swi, swif)을 무시해야할 때 사용할 수 있을 것입니다.
Observing events
observable을 observable 이벤트로 변환해야할 수 있습니다.
[코드]
example(of: "materialize and dematerialize") {
// 1
enum MyError: Error {
case anError
}
let disposeBag = DisposeBag()
// 2
let ryan = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 100))
let student = BehaviorSubject(value: ryan)
// 3
let studentScore = student
.flatMapLatest{
$0.score
}
// 4
studentScore
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 5
ryan.score.onNext(85)
ryan.score.onError(MyError.anError)
ryan.score.onNext(90)
// 6
student.onNext(charlotte)
/* Prints:
80
85
Unhandled error happened: anError
*/
}
error가 studentScore의 종료를 발생시키기 때문에 student도 종료되므로 Error가 발생합니다.
이 때, materialize 연산자를 사용하면 각각 방출되는 이벤트를 이벤트의 observable로 만들 수 있습니다.

let studentScore = student
.flatMapLatest {
$0.score.materialize()
}
/*
--- Example of: materialize and dematerialize ---
next(80)
next(85)
error(anError)
next(100)
*/
위 코드에 materialize()를 추가하면 studentScore의 타입은 Observable<Event<Int>>인 것을 확인할 수 있습니다.
그리고 현재 방출하는 이벤트를 구독하게 됩니다.
에러는 여전히 studentScore의 종료를 발생시키지만, student observable은 그대로 살려놓게 됩니다.
그러므로 새로운 학생인 charlotte를 추가하였을 때, 해당 학생의 점수 100이 성공적으로 출력됩니다.
하지만, 이 경우에도 event만 받을 뿐 요소들을 받을 수 없습니다.
이를 해결하기 위해 dematerialize를 사용합니다.

dematerialize는 기존의 모양으로 되돌려주는 역할을 합니다.
[코드]
studentScore
// 1
.filter {
guard $0.error == nil else {
print($0.error!)
return false
}
return true
}
// 2
.dematerialize()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
/*
--- Example of: materialize and dematerialize ---
80
85
anError
100
*/
dematerialize를 통해 studentScore observable을 원래 모양으로 리턴하고, 점수와 정지 이벤트를 방출할 수 있도록 합니다.
'iOS > RxSwift' 카테고리의 다른 글
[RxSwift] NotificationCenter, Notification (0) | 2022.11.21 |
---|---|
[RxSwift] Combining Operators (0) | 2022.11.18 |
[RxSwift] Filtering Operators (0) | 2022.10.12 |
[RxSwift] Subjects (0) | 2022.10.12 |
[RxSwift] Observable (0) | 2022.10.11 |