Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] (Rx의 원리) Observer vs Observable vs Subject, Subscribe 본문

RxSwift/RxSwift 기본

[iOS - swift] (Rx의 원리) Observer vs Observable vs Subject, Subscribe

jake-kim 2021. 7. 5. 02:12

핵심: Observable이 이벤트 방출, Oserver가 subscribe

Observer

  • Observable안에 있는 내부 인스턴스들로 Observable의 값에 변화가 있을 때 didSet 원리로 Observer에게 알림이 가고, Observer가 등록한 closure를 실행

Observable

  • Observer 인스턴스를 가지는 상태
  • value 인스턴스를 가지고 있다가, value가 변경되면 didSet을 통해 아이템 방출

Subscribe

  • observe()의 의미와 동일
  • Observable의 값이 변경될 때마다 '특정 작업'을 위한 closure블럭을 같이 넘김으로서 그 closure블럭이 실행되게끔 설정

Subject

  • Observable과 Observer의 성격 모두 가지고 있는 Protocol (이벤트 방출과, Subscribe를 이 타입 하나로 모두 가능)
    • subject가 없이 이벤트 처리를 한다면, observer, Observable 두 개의 타입이 필요
  • Observable은 1:1로 이벤트를 방출하지만 1:multi로 이벤트를 여러 Observer에게 송신

직접 Observable을 구현하여 원리 이해

  • Observable 기본 구현
    • Observable은 observer객체들을 가지고 있고, Observable의 값을 대입하면, Observer들에게 알리는 형태
  • Observer의 구성 요소
    • weak var observer: 클래스를 나타내며, Observer들을 해제할 때 클래스 구분 값으로 사용
    • blcok: 데이터가 방출된 경우 block을 실행하기 위함
public final class Observable<T> {

    struct Observer<T> {
        weak var observer: AnyObject?
        let block: (T) -> Void
    }

    private var observers = [Observer<T>]()

    public var value: T {
        didSet { notifyObservers() } // stord property에 값을 지정하면 -> block실행
    }

    public init(_ value: T) {
        self.value = value
    }

    private func notifyObservers() {
        for observer in observers {
            DispatchQueue.main.async { observer.block(self.value) }
        }
    }
}
  • observer가 추가되는 observe, remove함수 추가
public final class Observable<T> {

    ...

    /// observer를 추가: value값과 block 추가
    public func observe(on observer: AnyObject, observerBlock: @escaping (T) -> Void) {
        observers.append(Observer(observer: observer, block: observerBlock))
        observerBlock(value)
    }

    public func remove(observer: AnyObject) {
        observers = observers.filter { $0.observer !== observer }
    }
    
    ...
}
  • Observable 전체 코드
public final class Observable<T> {

    struct Observer<T> {
        weak var observer: AnyObject?
        let block: (T) -> Void
    }

    private var observers = [Observer<T>]()

    public var value: T {
        didSet { notifyObservers() } // stord property에 값을 지정하면 -> block실행
    }

    public init(_ value: T) {
        self.value = value
    }

    /// observer를 추가: value값과 block 추가
    public func observe(on observer: AnyObject, observerBlock: @escaping (T) -> Void) {
        observers.append(Observer(observer: observer, block: observerBlock))
    }

    public func remove(observer: AnyObject) {
        observers = observers.filter { $0.observer !== observer }
    }

    private func notifyObservers() {
        for observer in observers {
            DispatchQueue.main.async { observer.block(self.value) }
        }
    }
}

ex) Observable사용 예제

  • 사용하는 쪽 - ViewController에서 bind
    private func bind(to viewModel: MyViewModel) {
        viewModel.count.observe(on: self, observerBlock: { [weak self] in self?.updateCount(count: $0) })
    }
  • 사용하는 쪽 - ViewModel에서의 이벤트 방출
    var count: Observable<Int> = Observable(0)
    ...
    private func updateCount() {
        let currentCount = count.value != 0 ? count.value : dependencies.initCount
        count.value = currentCount + 1
    }

* Observable 예제 소스코드: https://github.com/JK0369/observable_ex

 

* 참고

http://reactivex.io/documentation/observable.html

Comments