[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple/Combine & Rx

[RxSwift] Relay (PublishRelay, BehaviorRelay, ReplayRelay)

inu 2022. 2. 25. 17:35
반응형

안녕하세요 이누입니다.


오늘은 Relay입니다!


RxSwift - Relay

Relay는 RxSwfit가 아니라 RxCocoa에 속하는 개념입니다. 그 종류에는 PublishRelay, BehaviorRelay, ReplayRelay가 있습니다.

 

Subject는 .completed, .error의 이벤트가 발생하면 subscribe가 종료되는 반면, Relay는 .completed, .error를 발생하지 않고 Dispose되기 전까지 계속 작동하기 때문에 UI Event에서 사용하기 적절합니다. Subject를 Wrapping하는 형태로 구성되어 있습니다.

 

요약) UI에 사용하기 좋은 Subject의 변형. 내부에 Subject 들고 있음.

 

PublishRelay

/// PublishRelay is a wrapper for `PublishSubject`.
///
/// Unlike `PublishSubject` it can't terminate with error or completed.
public final class PublishRelay<Element>: ObservableType {
    private let subject: PublishSubject<Element>

    // Accepts `event` and emits it to subscribers
    public func accept(_ event: Element) {
        self.subject.onNext(event)
    }

    /// Initializes with internal empty subject.
    public init() {
        self.subject = PublishSubject()
    }

    /// Subscribes observer
    public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
        self.subject.subscribe(observer)
    }

    /// - returns: Canonical interface for push style sequence
    public func asObservable() -> Observable<Element> {
        self.subject.asObservable()
    }
}
  • PublishSubject의 Wrapper 클래스입니다.
  • PublishSubject와는 다르게 completed 혹은 error와 함께 종료될 수 없습니다.
  • accept 메서드를 통해 이벤트를 받고 subscriber에게 전송합니다.
  • 내부에 PublishSubject가 있기 때문에 그 외 특징은 PublishSubject와 동일합니다. (초기값 없음)

BehaviorRelay

/// BehaviorRelay is a wrapper for `BehaviorSubject`.
///
/// Unlike `BehaviorSubject` it can't terminate with error or completed.
public final class BehaviorRelay<Element>: ObservableType {
    private let subject: BehaviorSubject<Element>

    /// Accepts `event` and emits it to subscribers
    public func accept(_ event: Element) {
        self.subject.onNext(event)
    }

    /// Current value of behavior subject
    public var value: Element {
        // this try! is ok because subject can't error out or be disposed
        return try! self.subject.value()
    }

    /// Initializes behavior relay with initial value.
    public init(value: Element) {
        self.subject = BehaviorSubject(value: value)
    }

    /// Subscribes observer
    public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
        self.subject.subscribe(observer)
    }

    /// - returns: Canonical interface for push style sequence
    public func asObservable() -> Observable<Element> {
        self.subject.asObservable()
    }
}
  • BehaviorSubject의 Wrapper 클래스입니다.
  • BehaviorSubject와는 다르게 completed 혹은 error와 함께 종료될 수 없습니다.
  • accept 메서드를 통해 이벤트를 받고 subscriber에게 전송합니다.
  • 내부에 BehaviorSubject가 있기 때문에 그 외 특징은 BehaviorSubject와 동일합니다. (초기값 필요, 값 보유)

ReplayRelay

/// ReplayRelay is a wrapper for `ReplaySubject`.
///
/// Unlike `ReplaySubject` it can't terminate with an error or complete.
public final class ReplayRelay<Element>: ObservableType {
    private let subject: ReplaySubject<Element>

    // Accepts `event` and emits it to subscribers
    public func accept(_ event: Element) {
        self.subject.onNext(event)
    }

    private init(subject: ReplaySubject<Element>) {
        self.subject = subject
    }

    /// Creates new instance of `ReplayRelay` that replays at most `bufferSize` last elements sent to it.
    ///
    /// - parameter bufferSize: Maximal number of elements to replay to observers after subscription.
    /// - returns: New instance of replay relay.
    public static func create(bufferSize: Int) -> ReplayRelay<Element> {
        ReplayRelay(subject: ReplaySubject.create(bufferSize: bufferSize))
    }

    /// Creates a new instance of `ReplayRelay` that buffers all the sent to it.
    /// To avoid filling up memory, developer needs to make sure that the use case will only ever store a 'reasonable'
    /// number of elements.
    public static func createUnbound() -> ReplayRelay<Element> {
        ReplayRelay(subject: ReplaySubject.createUnbounded())
    }

    /// Subscribes observer
    public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
        self.subject.subscribe(observer)
    }

    /// - returns: Canonical interface for push style sequence
    public func asObservable() -> Observable<Element> {
        self.subject.asObserver()
    }
}
  • ReplaySubject의 Wrapper 클래스입니다.
  • ReplaySubject와는 다르게 completed 혹은 error와 함께 종료될 수 없습니다.
  • accept 메서드를 통해 이벤트를 받고 subscriber에게 전송합니다.
  • 내부에 ReplaySubject가 있기 때문에 그 외 특징은 ReplaySubject와 동일합니다. (버퍼 보유)
반응형