티스토리 뷰

반응형

1. Subject 

1.1 Publish Subject 

- default값(초기값)이 없다 

- 다른 옵져버가 subscribe한 순간 아무것도 주지 않지만 데이터가 발생하면 다 준다

 

1.2 Behavior Subject 

- default(초기값) 을 넣어주어야한다

- 값이 없을때 (초기값만 있을 때) subscribe하면 초기값을 주고, 값이 있을때 subcribe하면가장 최근의 것을 준다 

- 중간에 error가 나면 subscribe하고 있는 모든 옵져버들한테 에러가 간다 

 

1.3 ReplaySubject 

- default값(초기값)이 없다 

- 다른 옵져버가 subscribe하면 여태까지 발생했던것 다 준다 

 

1.4 AsyncSubject

- default값(초기값)이 없다 

- Subject가 complete되면 가장 마지막 데이터를 그때서야 다른 옵져버에게 넘겨준다 

 

https://eunjin3786.tistory.com/36 (코드블럭 색깔이 안나와서 보기 안좋지만 Subject 자세히 정리한 것)

2. Relay  

- Relay들은 RxRelay에 있고 Rxcocoa를 import하면 쓸 수 있다 

- Publish Relay와 Behavior Relay가 있다 

- onNext가 아니라 accept이다 (accept안에 onNext가 구현되어있음)

- error랑 complete보낼 수 없다 오로지 accept만…!!!… 

- 에러도 안나고 complete도 안난다. 에러나도 무시 / 컴플리트나도 무시된다 
- 죽지않는 아이 relay…!…. 스트림이 종료가 안된다 <-> Subject는 컴플리트나 에러나면 그 스트림은 종료된다

- UI는 에러났다고 화면안그려 하거나 / input 스트림이 에러났다고 더이상 input 안받을거야—!! 하면 안된다 
    ===> 그래서 UI용으로 만들어놓은 것이 Relay이다. 

 

2.1 Publish Relay 

-Publish Subject를 래핑함 

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

    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<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
        return self._subject.subscribe(observer)
    }
    
    /// - returns: Canonical interface for push style sequence
    public func asObservable() -> Observable<Element> {
        return self._subject.asObservable()
    }
}

 

2.2 Behavior Relay 

-Behavior Subject를 래핑함 

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

    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<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
        return self._subject.subscribe(observer)
    }

    /// - returns: Canonical interface for push style sequence
    public func asObservable() -> Observable<Element> {
        return self._subject.asObservable()
    }
}

 

3. Driver 

Subject가 Relay가 된 것처럼 Observable이 에러를 무시하고 싶다면 다른 것으로 바뀌어야한다 ==> asDriver() 

pwField.rx.text.orEmpty
               .subscribe(onNext: viewModel.passwordInput)
               .disposed(by: disposeBag)
pwField.rx.text.orEmpty 
                .asDriver()
                .drive(onNext: viewModel.passwordInput)
                .disposed(by: disposeBag)

 

- driver로 바뀌면 subscribe가 아니라 drive를 해야한다

- drive는 onError가 없다 

- UI용이다. RxCocoa를 import해야지 asDriver()를 쓸 수 있다

- Main Scheduler에서 동작한다. observeOn(MainScheduler.instance) 해줄 필요없다 --! 

 

 

==> Relay와 Driver는 UI용으로 만들어놓은 것이다 (in Rxcocoa)

 

 

4. Variable 

Variable을 쓰면 이런 메세지가 뜬다.

 

ℹ️ [DEPRECATED] `Variable` is planned for future deprecation. Please consider `BehaviorRelay` as a replacement. Read more at: https://git.io/vNqvx

 

Moving *Relay into their own Framework. · Issue #1501 · ReactiveX/RxSwift

No deprecation warning in Xcode on using Variable: As per release notes provided here, Variable is deprecated in the favor of BehaviorRelay. But I dont see any deprecation warning on using Variable...

github.com

 

Behavior Relay와 Variable은 모두 BehaviorSubject을 래핑한 것이다. 

하지만 Behavior Relay의 value는 get-only(읽기전용) 이고 Variable의 value는 get,set(읽기쓰기가능) 이 가능하다. 

 

Behavior Relay에 구현되어있는 value 

    /// 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()
    }

 

Variable에 구현되어있는 value 

    public var value: E {
        get {
            self._lock.lock(); defer { self._lock.unlock() }
            return self._value
        }
        set(newValue) {
            #if DEBUG
                self._synchronizationTracker.register(synchronizationErrorMessage: .variable)
                defer { self._synchronizationTracker.unregister() }
            #endif
            self._lock.lock()
            self._value = newValue
            self._lock.unlock()

            self._subject.on(.next(newValue))
        }
    }

 

이런식으로 안의 구현체를 안보고 

 

간단하게 value에 값을 set해보면서도 차이점을 알 수 있다 :) 

 

 

* Variable이 Deprecated 되는 이유 

폐지되고 있는(Deprecating) Variable
BehaviroRelay는 Variable 처럼 하나의 값을 가지고 있다. 하지만 BehaviorRelay의 값은 읽기 전용이다. Variable에서 사용하듯이 = 를 사용해서 값을 대입하지 못한다.
Variable의 값을 대입하는 것은 명령형 프로그래밍 스타일이다. 그래서 선언형 프로그래밍 스타일인 Reactive의 초기에는 포함되어 있지 않았을 것이라 생각한다. 향후에 Variable은 사용되지 않을 것이고 BehavoirRelay의 별칭처럼 사용될 것이다. 그래서 이제 부터 이것을 고려하는 것이 좋을 것이다.

https://medium.com/@hongseongho/번역-signal-and-relay-in-rxcocoa-4-619d5194dcbd

 




Reference

곰튀김님의 강의영상을 토대로 내용을 붙이고 정리하였다 :) 

https://www.youtube.com/watch?v=YOsnXawC6wc 

반응형
댓글