일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- ios
- Protocol
- swiftUI
- 스위프트
- collectionview
- UITextView
- Clean Code
- swift documentation
- uiscrollview
- 애니메이션
- SWIFT
- ribs
- map
- Refactoring
- 클린 코드
- MVVM
- Observable
- clean architecture
- rxswift
- 리펙토링
- uitableview
- HIG
- tableView
- combine
- 리펙터링
- 리팩토링
- UICollectionView
- RxCocoa
- Xcode
- Human interface guide
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[RxSwift] 7.Transforming Operators 본문
1. Transforming elements
1) toArray
- 개별 원소들 -> 하나의 배열로
example(of: "toArray") {
let disposeBag = DisposeBag()
Observable.of("A", "B", "C")
.toArray()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
// prints : ["A", "B", "C"]
2) map
이벤트를 mapping하여 주어진 식을 통해 새로 변경
example(of: "map") {
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)
}
3) enumerated와 map
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)
}
/* prints
1
2
3
8
10
12
*/
2. Transforming inner observables
1) flatMap
각 하나의 sequence에서 각 event에 대해 sequence를 만든 후,
최종적으로 하나의 sequence로 만드는 것
- 1번 : 01엘리먼트가 flatMap을 만나 새로운 시퀀스 생성, 최종 시퀀스로 전달
- 2번 : 02엘리먼트가 flatMap을 만나 새로운 시퀀스 생성, 최종 시퀀스로 전달
- 3번 : 01엘리먼트의 value에 변동이 생김(10 -> 40), 최종 시퀀스로 전달
- 4번 : 02엘리먼트의 value에 변동이 생김(20 -> 50), 최종 시퀀스로 전달
//
struct Student {
var score: BehaviorSubject<Int>
}
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) // Print: 80
// 6
ryan.score.onNext(85) // Print: 80 85
// 7
student.onNext(charlotte) // Print: 80 85 90
// 8
ryan.score.onNext(95) // Print: 80 85 90 95
// 9
charlotte.score.onNext(100) // Print: 80 85 90 95 100
}
* 주석
1. 두 학생 객체 생성, 각 score를 갖는 BehaviorSubject객체로 초기화
2. 바로 전의 두 학생 객체의 score에 대한 이벤트를 처리하기 위해 PublishSubject객체 생성
3. student시퀀스를 score값을 기준으로 flatMap 변환
4. 변환된 시퀀스에 구독 요청 및 이벤트 print()
* map vs flatMap
map | flatMap | |
변경 :Observable<Int>.just(10) -> Observable<String>.just(10) |
이벤트를 가지고 변경 String($0) |
새로운 Observable를 생성하여 변경 Observable<String>.just(String($0)) |
접근 | 클로저에 연산 값 리턴 let n = Observable<Int>.just(10) let m = n.map{ String($0) } |
Observable리턴 let n = Observable<Int>.just(10) let fm = n.map{Observable<String>.just(String($0)} |
2) flatMapLatest
- 가장 최근에 만들어진 sequence만 emit
- 1번 : 01엘리먼트가 flatMap을 만나서 새로운 시퀀스 생성, 최종 시퀀스에 전달
- 2번 : 동일, 바로 뒤 30은 전달이 안되는 이유는 가장 마지막에 생성된 시퀀스는 20시퀀스이므로 20시퀀스에 대해서만 반응
- 3번 : 동일, 가장 마지막에 생성된 시퀀스는 40시퀀스이므로 뒤에 60도 최종 시퀀스에 전달
(그 당시 최근의 sequence는 1번으로 만들어진 것이 아닌, 2번의 sequence이므로)
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(onNext: {
print($0)
})
.disposed(by: disposeBag)
student.onNext(laura) // print : 80
laura.score.onNext(85) // print : 85
student.onNext(charlotte) // print : 90
laura.score.onNext(95) // print : none
charlotte.score.onNext(100) // print : 100
}
3. Observing events
- materialize 연산자 : 이벤트 타입으로 변환 후, Obervable 형으로 나타내는 것 Observable<Event<Int>>
- 용도 : elements가 아닌, events(onNext, onError, onCompleted)에서 이벤트를 처리하는 연산자
1) materialize를 쓰지 않은 경우
<이벤트 정의, 필요한 객체 생성>
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)
}
<onError이벤트에 대한 따로 처리가 없기 때문에 중간에 종료>
example(of: "materialize and dematerialize") {
// 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)
let studentScore = student
.flatMapLatest {
$0.score
}
studentScore
.subscribe(onNext: {
print($0) // print : 80
})
.disposed(by: disposeBag)
laura.score.onNext(85) // print : 85
laura.score.onError(MyError.anError) // print : Unhandled error happened: anError
laura.score.onNext(90) // print : none
student.onNext(charlotte) // print : none
}
2) materlize 사용
- next이벤트(Int타입)를 Event타입으로 변환
- onError이벤트를 Event타입으로 변환
- onCompleted이벤트를 Event타입으로 변환
// (... 중략 ...)
let studentScore = student
.flatMapLatest {
$0.score.materialize()
}
// (... 하략 ...)
/* prints
next(80)
next(85)
error(anError)
next(100)
*/
'RxSwift > RxSwift 기본' 카테고리의 다른 글
[RxSwift] 9. Combining Operators (0) | 2020.06.05 |
---|---|
[RxSwift] 8. Transforming Operators 실전(RESTful API) (0) | 2020.06.04 |
[RxSwift] 6.Filtering Operators 실습 (0) | 2020.05.29 |
[RxSwift] 5.Filtering Operators (0) | 2020.05.26 |
[RxSwift] 4. Observables and Subjects 실전 적용 (0) | 2020.05.25 |