https://rhammer.tistory.com/304
Materialize/dematerialize
third party 프레임워크에 의해 생성될 수 있는, sequence 제어가 제한되거나 제어가 불가능해서 발생하는 에러를 처리하는 해결책.
관찰 가능 이벤트를 관찰 가능 이벤트로 변환하려는 경우가있을 수 있습니다. 이것이 유용한 일반적인 시나리오 중 하나는 관찰 가능한 속성이있는 관찰 가능 개체를 제어 할 수없고 외부 시퀀스가 종료되지 않도록 오류 이벤트를 처리하려는 경우입니다.
- materialize 연산자는 어떤 sequence든 Event<T> enum sequence로 변환한다.
- Original
- Data → X
- Data → Completed
- Materialized
- Event<Data> → Event<Error>
- Event<Data> → Event<Completed>
- Original
- 이 연산자를 이용하면 적절한 연산자와 여러가지 handler로 조작되는 암시적인 sequence들을 명시적으로 변환할 수 있다.
- 따라서 onNext, onError, onCompleted는 각각의 함수로써 조작될 수 있다.
- dematerialize를 사용하여 notification sequence를 뒤집을 수 있다.
- Materialized
- Event<Data> → Event<Error>
- Event<Data> → Event<Completed>
- Dematerialize
- Data → X
- Data → Completed
- Materialized
- materialize와 dematerialize는 보통 함께 쓰인다. 이 둘을 함께 쓰면 원본 observable을 완전히 분해할 수 있다. 다만, 특정 상황을 처리할 수 있는 다른 옵션이 없을 때만 신중하게 사용해야 한다.
- 이 두가지 연산자를 병합해서 커스텀한 이벤트 기록기를 만들 수 있다.
observableToLog.materialize()
.do(onNext: { (event) in
myAdvancedLogEvent(event)
})
.dematerialize()
Example in Raywenderlich RxSwift Book
- Materialize
- Observable<Int> → Observable<Event<Int>>
- Dematerialize
- Observable<Event<Int>> → Observable<Int>
struct Student {
var score: BehaviorSubject<Int>
}
enum MyError: Error {
case anError
}
let ryan = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 100))
let student = BehaviorSubject(value: ryan)
let studentScore = student
.flatMapLatest {
$0.score
}
studentScore
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
ryan.score.onNext(85)
ryan.score.onError(MyError.anError)
ryan.score.onNext(90)
student.onNext(charlotte)
// 80
// 85
// Received unhandled error: RxSwiftPlayground.playground:....
Materialize
let studentScore = student
.flatMapLatest {
$0.score.materialize()
}
// next(80)
// next(85)
// error(anError)
// next(100)
Dematerialize
studentScore
.filter {
guard $0.error == nil else {
print($0.error!)
return false
}
return true
}
.dematerialize()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 80
// 85
// anError
// 100
댓글