[RxSwift] 1. Observable

dev-yong·2022년 1월 9일
0

RxSwift

목록 보기
1/8

Basics

  • 모든 Observable sequence은 단지 sequence이다
  • Sequence는 0개 혹은 더 많은 element를 갖을 수 있다.
  • error 혹은 completed 이벤트를 받을 때, sequence는 더이상 element를 생산해낼 수 없다.
enum _Event<Element> {

    case next(Element)
    case error(Swift.Error)
    case completed

}
protocol _ObserverType {

    associatedtype Element
    func on(_ event: Event<Element>)

}
protocol _ObservableType {

    associatedtype Element

    func subscribe<Observer: ObserverType>(
        _ observer: Observer
    ) -> Disposable where Observer.Element == Element
}
class _Observable<Element>: ObservableType {

    func subscribe<Observer>(
        _ observer: Observer
    ) -> Disposable
    where Observer : ObserverType, Element == Observer.Element {
        fatalError()
    }

}

Creating

  • Observable은 sequence의 생성 방법과 element 요소 생성에 사용되는 parameter를 정의할 뿐이다.
  • subscribe 메서드가 호출되어야 sequence가 시작된다.
func syncObservable<E>(_ element: E) -> Observable<E> {
    return Observable.create { observer in
        observer.on(.next(element))
        observer.on(.completed)
        return Disposables.create()
    }
}
func asyncObservable(_ interval: DispatchTimeInterval) -> Observable<Int> {
    return Observable.create { observer in
        print("Subscribed")
        let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
        timer.schedule(deadline: DispatchTime.now() + interval, repeating: interval)

        let cancel = Disposables.create {
            print("Disposed")
            timer.cancel()
        }

        var next = 0
        timer.setEventHandler {
            if cancel.isDisposed {
                return
            }
            observer.on(.next(next))
            next += 1
        }
        timer.resume()

        return cancel
    }
}

empty

  • element를 하나도 갖지 않는 Observable을 생성한다.
  • completed 이벤트만 방출한다.
  • 즉시 종료할 수 있는 Observable 반환하고자 할 때 시용한다.
Observable<Void>.empty()
.subscribe(
    onNext: { print("Element :", $0) },
    onCompleted: { print("Completed") }
)

never

  • completed 이벤트마저 방출되지 않는, 종료되지 않는 Observable을 반환한다.
Observable<Void>.never()
.subscribe(
    onNext: { print("Element : ", $0) },
    onCompleted: { print("Completed") }
)

deferred

  • “연기하다”
  • 실제 Observable이 만들어지는 시점을 미룬다.
  • Observable을 만들어내는 factory closure를 인자로 받는다.
  • 실제로 구독이 일어나는 시점에서야 Observable을 만들어 낸다.
 static func _deferred(_ observableFactory: @escaping () throws -> Observable<Element>)
var flag = false
let deferred = Observable<Int>.deferred {
    flag.toggle()
    return flag ? Observable.from([1, 2, 3]) : Observable.from([4, 5, 6])
}

deferred
    .debug()
    .subscribe()
    .disposed(by: disposeBag)

deferred
    .debug()
    .subscribe()
    .disposed(by: disposeBag)

Disposing

  • dispose를 직접 호출하는 것은 bad code smell이 나기 때문에 지양하도록 한다.
    • DisposeBag, takeUntil과 같은 메커니즘을 이용하여 subscription을 dispose하는 것이 더 좋은 방법이다.
  • dispose가 호출되면, 해당 seqeunce는 더이상 작동하지 않는다.
  • 만일 dispose() 혹은 DisposeBag에 disposable을 추가하는 등의 행위를 하지 않는다면? Observable이 완료되지 않으면 메모리 누수가 날 것이다.
public protocol _Disposable {

    func dispose()
}

Dispose Bags

  • DisposeBag이 deallocate될 때, 추가되어져있던 Disposable들의 dispose를 호출한다.
    • dispose 메서드를 갖지 않으며, 즉 명시적인 호출을 허용하지 않는다.
    • 바로 정리가 필요할 경우 새롭게 생성한다.
    self.disposeBag = DisposeBag()

Hot vs Cold Observable

Hot

  • 생성과 동시에 이벤트를 방출하기 시작한다.
    • Subscribe 되는 시점과 상관없이 Observer들에게 이벤트를 중간부터 전송한다.
    • 생성과 동시에 리소스를 소모한다.
  • 여러 Observer가 하나의 Observable을 공유할 수 있다.
  • ConnectableObservable 로 불리우기도 한다.
  • e.g. .connect()

Cold

  • Observer가 Subscribe하는 시점부터 이벤트를 생성하여 방출한다.
    • Subscribe되기 전에는 리소스를 소모하지 않는다.
  • Observer마다 별도의 Observable 인스턴스를 갖는다.
profile
🧑🏻‍💻 iOS Developer @TOSS

0개의 댓글