RxSwift property observe (BehaviorRelay, Variable)
property 구독하기
property를 구독하기 위하여 BehaviorRelay를 사용한다.
RxSwift 4.0 이전에는 Variable을 사용했었다. 하지만 Variable은 Depreated가 예정 되었고 BehaviorRelay가 새로 나오게 되었다.
Variable을 사용하게 되면 xcode console창에 아래와 같이 경고가 발생한다.
https://play.google.com/store/apps/details?id=com.danchoo.tagalbum&hl=ko
Variable은 deprecated가 예정되었습니다. BehaviorRelay로 변경해주세요.
[DEPRECATED] `Variable` is planned for future deprecation. Please consider `BehaviorRelay` as a replacement. Read more at: https://git.io/vNqvx
Variable (Deprecated)
Variable 부터 살펴보려고 한다.
Variable : 변동이 심한, 가변적인, 변화를 줄 수 있는, 변수
모든 뜻이 RxSwift의 Variable과 맞아 떨어지는 것 같다.
하지만 '변화를 줄 수 있는'이라는 뜻이 RsSwift의 Variable의 의미라고 생각이 든다.
Variable은 BehaviorSubject를 한번 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)
Variable의 코드를 복사해 왔다.
내부 구조를 보지 않아도 상관은 없지만 한번이라도 보면 도움이 되는것 같아 복사해 왔다.
https://smartstore.naver.com/happysiso
======================================================================================================
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로 되어있다.
Variable은 value를 public 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 : (정보뉴스 등을 받아서) 전달하다
BehaviorRelay는 BehaviorSubject를 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)
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 property로 value를 가지고 있다. value를 보면 self._subject.value()를 return하고 있다.
self._subject.value()는 함수이기 때문에 value에 직접적으로 set이 불가능 하다.
그렇기 때문에 value로 직접 값을 넣지 못하게 되어있고 accept를 통해서 값을 넣을수있도록 되어있다.
accept는 onNext이벤트를 발생 시켜 이벤트로 값을 셋팅하도록 만든다.
초기값을 제외한 모든 값의 변경은 이벤트로 이루어진다.
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
======================================================================================================
'iOS > Swift' 카테고리의 다른 글
RxSwift UITableView (1) - One Section, One Cell, More Cell (1) | 2019.07.15 |
---|---|
RxSwift UITextField (0) | 2019.06.01 |
RxSwift 객체 구독하기 (Observable) (0) | 2019.05.18 |
RxSwift 시작하기 (설치 & Button Tap Event - DisposeBag, rx.Tap ) (0) | 2019.05.03 |
RxSwift (ReactiveX) (0) | 2019.04.26 |
댓글