본문 바로가기
iOS/Swift

RxSwift property observe (BehaviorRelay, Variable)

by DnaJ 2019. 5. 25.
반응형

RxSwift property  observe (BehaviorRelay,  Variable)

property 구독하기

property를 구독하기 위하여 BehaviorRelay를 사용한다.

RxSwift 4.0 이전에는 Variable을 사용했었다. 하지만 Variable Depreated가 예정 되었고 BehaviorRelay가 새로 나오게 되었다.

Variable을 사용하게 되면 xcode console창에 아래와 같이 경고가 발생한다.

 

 

Variable은 deprecated가 예정되었습니다. BehaviorRelay로 변경해주세요.

[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

 

 

Variable (Deprecated)

Variable 부터 살펴보려고 한다.

Variable :  변동이 심한, 가변적인, 변화를 줄 수 있는,  변수

모든 뜻이 RxSwift의 Variable과 맞아 떨어지는 것 같다.

하지만 '변화를 줄 수 있는'이라는 뜻이 RsSwift의 Variable의 의미라고 생각이 든다.

VariableBehaviorSubject를 한번 wraping 한것이다.

 

BehaviorSubject

A Subject that requires an initial value and emits its current value to new subscribers

초기 값이 필요하고 현재 구독자에게 새 값을 보내는 주제

BehaviorSubject는 Observable<Element> 확장하고 있다.

2019/05/18 - [iOS/Swift] - RxSwift 객체 구독하기 (Observable)

 

RxSwift 객체 구독하기 (Observable)

RxSwift 객체 구독하기 (Observable) 포스팅 하기에는 정말 민망할 정도로 자세하게 홈페이지에 설명이 작성되어 있다. 영어로 작성이 되어있지만 오른쪽에 한국어로 변경이 가능하도록 되어 있어 편하게 볼수 있..

myseong.tistory.com

Variable의 코드를 복사해 왔다. 

내부 구조를 보지 않아도 상관은 없지만 한번이라도 보면 도움이 되는것 같아 복사해 왔다.

======================================================================================================

public final class Variable<Element> {

    public typealias E = Element

    private let _subject: BehaviorSubject<Element>

    private var _lock = SpinLock()

    // state
    private var _value: E

    #if DEBUG
    fileprivate let _synchronizationTracker = SynchronizationTracker()
    #endif

    /// Gets or sets current value of variable.
    ///
    /// Whenever a new value is set, all the observers are notified of the change.
    ///
    /// Even if the newly set value is same as the old value, observers are still notified for change.
    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))
        }
    }

    /// Initializes variable with initial value.
    ///
    /// - parameter value: Initial variable value.
    public init(_ value: Element) {
        #if DEBUG
            DeprecationWarner.warnIfNeeded(.variable)
        #endif

        self._value = value
        self._subject = BehaviorSubject(value: value)
    }

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

    deinit {
        self._subject.on(.completed)
    }
}

======================================================================================================

 

 

value의 앞을 보면 public func가 아니라 public var로 되어있다. 

Variablevaluepublic property 가지고 있고, setter에서 _value에 대입을 하고

subject.on(.next(newValue))로 이벤트를 생성하고 있기 때문에 아래코드와 같이 사용이 가능하다.

======================================================================================================

let disposeBag = DisposeBag()

let intPropertyVariable = Variable(1)
func changeProperty() {
		// subscribe로 property를 구독한다
        intPropertyVariable.asObservable()
            .subscribe(onNext: { newValue in
                print("newValue - \(newValue) ")
            }).disposed(by: disposeBag)
        
        // value 2로 변경
        intPropertyVariable.value = 2
}

======================================================================================================

 

출력 결과

newValue - 1

newValue - 2

 

======================================================================================================

 

 

 

BehaviorRelay

이제는 Variable이 Deprecated되기 때문에 더이상 사용하지 말고 BehaviorRelay를 사용하자.

 

Behavior : 행동, 거동, 행실, 품행, 태도

Relay (정보뉴스 등을 받아서) 전달하다 

 

BehaviorRelayBehaviorSubjectwraping하고 있다.

 

BehaviorSubject

A Subject that requires an initial value and emits its current value to new subscribers

초기 값이 필요하고 현재 구독자에게 새 값을 보내는 주제

BehaviorSubject는 Observable<Element> 확장하고 있다.

2019/05/18 - [iOS/Swift] - RxSwift 객체 구독하기 (Observable)

 

RxSwift 객체 구독하기 (Observable)

RxSwift 객체 구독하기 (Observable) 포스팅 하기에는 정말 민망할 정도로 자세하게 홈페이지에 설명이 작성되어 있다. 영어로 작성이 되어있지만 오른쪽에 한국어로 변경이 가능하도록 되어 있어 편하게 볼수 있..

myseong.tistory.com

BehaviorRelay의 코드를 복사해 왔다. 

내부 구조를 보지 않아도 상관은 없지만 한번이라도 보면 도움이 되는것 같아 복사해 왔다.

======================================================================================================

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

======================================================================================================

 

BehaviorSubject public propertyvalue를 가지고 있다. value를 보면 self._subject.value()를 return하고 있다.

self._subject.value()는 함수이기 때문에 value에 직접적으로 set이 불가능 하다.

그렇기 때문에 value로 직접 값을 넣지 못하게 되어있고 accept 통해서 값을 넣을수있도록 되어있다.

 

acceptonNext이벤트를 발생 시켜 이벤트로 값을 셋팅하도록 만든다.

초기값을 제외한 모든 값의 변경은 이벤트로 이루어진다.

BehaviorSubject는 아래와 같이 사용할 수 있다.

 

======================================================================================================

let disposeBag = DisposeBag()
    let strProperty =  BehaviorRelay(value: "000")
    
    func changeProperty() {
        
        strProperty.subscribe( onNext: { newValue in
            print("newValue - \(newValue) ")
        }).disposed(by: disposeBag)
        
        self.strProperty.accept("111")
        self.strProperty.accept("222")
 
    }

======================================================================================================

 

출력 결과

newValue - 000

newValue - 111

newValue - 222

 

======================================================================================================

 

 

반응형

댓글