Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 팩토리메서드패턴
- 디자인패턴
- 상태패턴
- 전략패턴
- ViewController
- 커맨드패턴
- Scenedelegate
- 파사드패턴
- 옵저버패턴
- RxSwift
- 스테이트패턴
- 컴포지트패턴
- Mobile
- Lifecycle
- 어댑터패턴
- 스트래터지패턴
- WKWebView
- cocoapods
- 싱글턴패턴
- 데코레이터패턴
- DispatchQueue
- ios
- 이터레이터패턴
- 프록시패턴
- unowned
- SWIFT
- 템플릿메서드
- 추상팩토리패턴
- Xcode
- 컴파운드패턴
Archives
- Today
- Total
ios dev kangwook.
6. Transforming Operators 본문
Transforming elements
- Observable 은 아이템을 개별적으로 방출하지만 Observable을 UITableView 또는 UICollectionView에 바인딩 할 때와 같이 컬렉션 작업에 쓰려고 할 수도 있다.
- Observable 의 개별 아이템을 모든 아이템의 배열로 변환하는 편리한 방법은 toArray 를 사용하는 것
- toArray 는 Observable 시퀀스를 해당 아이템 배열로 변환하고 해당 배열을 포함하는 .next 이벤트를 구독자에게 내보낸다.
example(of: "toArray") {
let disposeBag = DisposeBag()
Observable.of("A", "B", "C")
.toArray()
.subscribe {
print($0)
}
.disposed(by: disposeBag)
}
- RxSwift의 map 연산자는 Observable에서 동작한다는 점을 제외하면 Swift의 표준 map과 동일하게 동작
example(of: "map") {
let disposeBag = DisposeBag()
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
Observable<Int>.of(123, 4, 56)
.map {
formatter.string(for: NSNumber(value: $0)) ?? ""
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
}
- 필터링 연산자와 함께 enumerated() 와 map을 사용할 수 있다.
example(of: "enumerated and map") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.enumerated()
.map { index, integer in
index > 2 ? integer * 2 : integer
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
}
Transforming inner observables
- 진행될 예제를 위해 다음 코드를 추가
struct Student {
let score: BehaviorSubject<Int>
}
- flatMap은 Observable 시퀀스의 각 아이템을 Observable 시퀀스에 투영하고 결과로 생성되는 Observable 시퀀스를 하나의 Observable 시퀀스로 병합
- flatMap은 Observable 값을 투영하고 변환한 다음 Observable 대상으로 평평하게 만든다.
example(of: "flatMap") {
let disposeBag = DisposeBag()
let laura = Student(score: BehaviorSubject(value: 80)) // Student 타입의 laura 인스턴스 생성
let charlotte = Student(score: BehaviorSubject(value: 90)) // Student 타입의 charlotte 인스턴스 생성
let student = PublishSubject<Student>() // Student 타입의 PublishSubject 생성
student
.flatMap { // flatMap을 사용해서 Student 내부의 score에 접근해서 투영
$0.score
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
}
- 다음 코드 추가
student.onNext(laura)
laura.score.onNext(85)
student.onNext(charlotte)
laura.score.onNext(95)
- flatMap은 각 Observable에서 변경 사항을 계속 투영한다.
- flatMapLatest는 map 과 switchLatest 의 조합
- switchLatest 는 가장 최근의 Observable에서 값을 생성하고 이전 Observable에서 구독을 취소
- 따라서 flatMapLatest는 Observable 시퀀스의 각 아이템을 Observable 시퀀스의 새로운 시퀀스로 투영한 다음 Observable 시퀀스를 Observable 시퀀스로 변환하여 가장 최근의 Observable 시퀀스에서만 값을 생성
- flatMapLatest 는 flatMap 처럼 동작하여 Observable 아이템에 접근하여 Observable 속성에 접근하고 각 아이템에 대한 새 시퀀스를 투영
- flatMapLatest 가 다른 점은 자동으로 최신 Observable 로 전환하고 이전 항목에서 구독을 취소
example(of: "flatMapLatest") {
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 {
print($0)
}
.disposed(by: disposeBag)
student.onNext(laura)
laura.score.onNext(85)
student.onNext(charlotte)
laura.score.onNext(95)
charlotte.score.onNext(100)
}
- flatMapLatest 는 가장 일반적으로 네트워크 작업과 함께 사용
- 예를 들어, 자동 완성 검색을 구현한다고 가정하면 사용자가 문자를 입력할 때 새 검색을 실행하고 이전 검색 결과를 무시할 수 있다.
Observing Events
- Observable을 해당 이벤트의 Observable로 변환하려는 경우가 있을 수 있다.
- 예를 들어, Observable 속성이 있는 Observable 항목을 제어할 수 없고 외부 시퀀스가 종료되지 않도록 오류 이벤트를 처리하려는 경우
example(of: "materialize and dematerialize") {
enum MyError: Error {
case anError
}
let disposeBag = DisposeBag()
let laura = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 100))
let student = BehaviorSubject(value: laura)
let studentScore = student.flatMapLatest { $0.score }
studentScore
.subscribe {
print($0)
}
.disposed(by: disposeBag)
laura.score.onNext(85)
laura.score.onError(MyError.anError)
laura.score.onNext(90)
student.onNext(charlotte)
}
- 여기서 studentScore 를 다음과 같이 바꾸면
let studentScore = student.flatMapLatest { $0.score.materialize() }
- 오류로 인해 studentScore는 종료되지만 외부 학생은 관찰되지 않으므로 새 학생으로 전환하면 해당 점수가 성공적으로 수신되고 출력된다.
- 이제는 아이템이 아닌 이벤트를 다루고 있다.
- 구체화된 Observable 항목을 원래의 형태로 변환
studentScore
.filter {
guard $0.error == nil else {
print($0.error!)
return false
}
return true
}
.dematerialize()
.subscribe {
print($0)
}
.disposed(by: disposeBag)
'RxSwift' 카테고리의 다른 글
8. Time-Based Operators (0) | 2022.12.27 |
---|---|
7. Combining Operators (1) | 2022.12.23 |
5. Filtering Operators (0) | 2022.12.19 |
4. Observables & Subjects in Practice (1) | 2022.12.13 |
3. RxSwift Subjects (0) | 2022.12.12 |
Comments