Combining Operator
SwitchLatest
🐣 두 개의 옵저버블 간에 원하는 옵저버블만 구독할 수 있게 전환하는 스위치 역할!
정의
🐣 Transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.
Each time a new inner observable sequence is received, unsubscribe from the previous inner observable sequence.
옵저버블 시퀀스들의 옵저버블 시퀀스를 가장 최근의 옵저버블 시퀀스로부터 값을 생성하는 옵저버블 시퀀스로 변형시킨다. 새로운 내부 옵저버블 시퀀스를 받을 때마다, 이전에 가지고 있던 내부 옵저버블 시퀀스를 구독해제한다.
public func switchLatest() -> Observable<Element.Element> {
Switch(source: self.asObservable())
}
final private class Switch<Source: ObservableConvertibleType>: Producer<Source.Element> {
private let source: Observable<Source>
init(source: Observable<Source>) {
self.source = source
}
override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Source.Element {
let sink = SwitchIdentitySink<Source, Observer>(observer: observer, cancel: cancel)
let subscription = sink.run(self.source)
return (sink: sink, subscription: subscription)
}
}
반환값 : 가장 최근에 받은 내부 옵저버블 시퀀스의 elements를 생성하는 observable 시퀀스를 반환한다.
옵저버블 시퀀스의 옵저버블 시퀀스? : 위 메서드의 반환형 Observable<Element.Element> 부분에서 앞 쪽의 Element가 옵저버블 시퀀스이고, 그 시퀀스의 Element를 반환하는 새로운 옵저버블을 만들겠다는 뜻!
쉽게 말해서, 여러 옵저버블 시퀀스들 중에서 원하는 옵저버블 시퀀스의 이벤트를 구독할 수 있도록 선택해주는 스위치 역할의 옵저버블을 만들어준다!
class SwitchLatestVC: UIViewController {
private let disposeBag = DisposeBag()
let one = PublishSubject<String>()
let two = PublishSubject<String>()
let three = PublishSubject<String>()
let source = PublishSubject<Observable<String>>()
let firstTFBehavior = BehaviorRelay<String>(value: " ")
let secondTFBehavior = BehaviorRelay<String>(value: " ")
lazy var switchSource = BehaviorSubject<BehaviorRelay<String>>(value: firstTFBehavior)
// 예시 1
private func testSwitchLatestByConsole() {
source
.switchLatest()
.subscribe(onNext: { value in print(value) })
.disposed(by: disposeBag)
source.onNext(one) // switched one
one.onNext("one 1") // one 1
two.onNext("two 1") //
source.onNext(two) // switched two
two.onNext("two 2") // two 2
one.onNext("one 2") //
source.onNext(three) // switched three
two.onNext("two 3") //
one.onNext("one 3") //
three.onNext("three 1") // three 1
source.onNext(one) // switched one
one.onNext("one 4") // one 4
}
// RxCocoa 적용 예시
private func bind() {
// MARK: SwitchLatest Operator 예시
firstTextField.rx.text.orEmpty
.bind(to: firstTFBehavior)
.disposed(by: disposeBag)
secondTextField.rx.text.orEmpty
.bind(to: secondTFBehavior)
.disposed(by: disposeBag)
mySwitch.rx.isOn
.subscribe(onNext: { isOn in
isOn
? self.switchSource.onNext(self.secondTFBehavior)
: self.switchSource.onNext(self.firstTFBehavior)
})
.disposed(by: disposeBag)
switchSource
.switchLatest()
.map { "SwitchLatest : " + $0 }
.asDriver(onErrorJustReturn: "오류")
.drive(testLabel.rx.text)
.disposed(by: disposeBag)
}
}
Merge
정의
🐣 Merges elements from all observable sequences in the given enumerable sequence into a single observable sequence.
모든 옵저버블 시퀀스를 병합해서 하나의 옵저버블 시퀀스처럼 합쳐준다
public func merge() -> Observable<Element.Element> {
Merge(source: self.asObservable())
}
예시
// 아래와 같이 rx.text로 control 프로퍼티에 접근해도 되고
let observableMerge = Observable.of(firstTextField.rx.text, secondTextField.rx.text)
observableMerge
.merge()
.map { "Merge : " + $0 }
.bind(to: mergeLabel.rx.text)
.disposed(by: disposeBag)
How to properly use switchLatest to toggle between search results and empty state of tableview?
서로 다른 자료형의 Observable을 하나로 묶기
RxSwift merge different kind of Observables
let stringSubject = PublishSubject<String>()
let stringObservable = stringSubject.asObservable().map { $0 as AnyObject }
let intSubject = PublishSubject<Int>()
let intObservable = intSubject.asObservable().map { $0 as AnyObject }
Observable.of(stringObservable, intObservable).merge()
.subscribeNext { print($0) }
.addDisposableTo(disposeBag)
stringSubject.onNext("a")
stringSubject.onNext("b")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("c")
'iOS' 카테고리의 다른 글
[If kakao 후기] 카카오뱅크 iOS 프로젝트의 모듈화 여정: Tuist를 활용한 모듈 아키텍처 설계 사례 (0) | 2023.02.17 |
---|---|
[Tuist 3.12.0] Tuist 및 Local Swift Package를 이용해 Platform 간 Source code 공유하기 (0) | 2023.02.16 |
[RxSwift] RxSwift 기본 (2편 - RxCocoa) (0) | 2023.01.06 |
[Combine] @dynamicMemberLookup 어트리뷰트로 assign에 사용할 keyPath 자동완성하기 (0) | 2022.12.06 |
[Combine] Combine과 RxSwift의 UI Binding 방식 비교(Feat. assign과 KeyPath) (0) | 2022.11.29 |