텍스트로만 공부했던 RxSwift 타입들을 어디에 써야할지 좀 감이 잡혀서 다시 정리하는 글
일단 다양한 Rx의 연산자는 reactivex.io에서 확인할 수 있다.
우선 Observable은 값을 방출하는 타이밍에 따라 Hot, Cold로 나눌 수 있다.
“Hot” and “Cold” Observables
When does an Observable begin emitting its sequence of items? It depends on the Observable. A “hot” Observable may begin emitting items as soon as it is created, and so any observer who later subscribes to that Observable may start observing the sequence somewhere in the middle. A “cold” Observable, on the other hand, waits until an observer subscribes to it before it begins to emit items, and so such an observer is guaranteed to see the whole sequence from the beginning.
출처: ReactiveX - Observable
Hot Observable: 외부에서 독립적으로 생성되어, 구독자 여부와 무관하게 데이터 스트림이 흐르며 값을 방출하고 있다. 생성 이후 구독하는 옵저버블은 아무때나 구독해도 방출하는 값을 받을 수 있다.
-> 여기에 오늘 정리할 subject, relay 등이 해당된다.
Cold Observable: 구독자가 생기기 전에는 데이터 스트림을 생성하지 않다가, 구독자가 생기면 새로운 스트림이 시작되고, 그 이후부터 값을 방출한다. 그래서 구독자는 구독 시작부터의 값을 모두 받아볼 수 있음
-> 다음에 정리할 Single, just등이 해당한다.
특히 헷갈렸던 Publish, Behavior는 냅다 외우면 외워지지가 않았는데 의미를 찾아보고 나니 이해하기 쉬웠다.
publish: to make information available to people, especially in a book, magazine, or newspaper, or to produce and sell a book, magazine, or newspaper
: 말 그대로 정보를 공개, 발행한다는 뜻으로, RxSwift에서는 초기값, 현재값 저장 없이 단순히 이벤트가 들어올 때마다 publish를 구독하고 있는 구독자들에게 정보를 방출한다.
behavior: 유래를 찾다가 이 글을 봤는데, OOP에서 state랑 behavior를 구분해서 이해할 수 있는 글이었다. 요약하자면 일반적으로 state는 저장된 상태, behavior는 그 상태를 변화하게 하는 로직 정도? 인 것 같다.
: RxSwift에서는 behavior가 state를 변화시키는 로직 그 자체를 의미하지는 않고, 현재 상태를 저장하고 그 상태를 기반으로 데이터 스트림을 발행한다.
: onNext 외에 onError, onCompleted가 필요한 상황에서 유용하다.
publishSubject: 다음 그림처럼 초기값도 없고, 구독 이후의 이벤트만 방출

behaviorSubject: 다음 그림처럼 초기값(분홍색 공)이 있고, 구독하면 가장 최근 상태를 방출해줌

이 외에도 다양한 subject가 있는데 여기 참고
: Relay는 기본적으로 Subject를 래핑한 클래스이다. onError 또는 onCompleted가 존재하지 않고 accept로 값만 전달할 수 있다.
UI에서는 onError나 onCompleted가 방출됐다가 스트림이 아예 끊겨버리는 상황이 발생할 수 있기 때문에, 주로 Relay를 사용한다.
주로 View, ViewController 단에서 UI 이벤트를 구독하는 데에 사용한다.
// Observer
private let buttonTap = PublishRelay<Void>()
private let cellTapped = PublishRelay<IndexPath>()
private let swipeGesture = PublishRelay<UISwipeGestureRecognizer.Direction>()
private let refreshTrigger = PublishRelay<Void>()
private let imageSelected = PublishRelay<UIImage>()
// Observable - Subscribe
saveButton.rx.tap
.bind(to: buttonTap)
.disposed(by: disposeBag)
tableView.rx.itemSelected
.bind(to: cellTapped)
.disposed(by: disposeBag)