0
votes

I'm wondering if there is a way in RxSwift to observe value of stored variable property. Eg. in following example:

    var updatedValue: Int = 0

    var observedValue: Observable<Int> {
            return Observable.create({ (observer) -> Disposable in
                observer.onNext(updatedValue)
                return Disposables.create()
            })
        }

    Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
        updatedValue = updatedValue + 1;
    }

    let myObservable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        .publish()

    myObservable.connect()

    myObservable
        .withLatestFrom(observedValue)
        .subscribe { (event) in
            print(event)
    }

We have variable property updatedValue and hot observable myObservable. We also increment value of updatedValue in Timer.scheduledTimer....

Flow here is pretty straight forward. When we subscribe, observedValue gets called, we get onNext from observedValue and then Disposables.create(). Then we print event onNext(0).

As myObservable is based on Observable.interval, same withLatestFrom value gets printed in onNext every second.

Question: Is there a way to print last value of updatedValue every time myObservable emits new event? So instead of 0,0,0... we get 0,1,2...

I'm aware that updatedValue could be declared as BehaviorRelay. I'm also aware that we could use .map { } to capture self.updatedValue.

But I'm wondering if there is any way to create a Observable wrapper around standard variable property so it calls onNext with most recent value every time trigger sequence sends an event? Without capturing self or changing declaration on updatedValue.

Thanks for any comments and ideas!

2
How about using rx KVO observation? It's fairly straightforward to observe changes of a stored property in a class.Tony Nguyen
@TonyNguyen indeed! That's exactly what I meant. let updatedValueObservable = self.rx.observe(Int.self, "updatedValue") seems to do the trick without any additional operators. Can you please post your comment so I can mark it as accepted one? ;)Kamajabu
Hey, thanks! I've posted my answer.Tony Nguyen

2 Answers

1
votes

RxCocoa has a handy wrapper around KVO. You should be able to use it from .rx extension on NSObject subclasses.

For your issue, I guess you can do something like:

let updatedValueObservable = self.rx.observe(Int.self, "updatedValue")
1
votes

But I'm wondering if there is any way to create a Observable wrapper around standard variable property so it calls onNext with most recent value every time trigger sequence sends an event? Without capturing self or changing declaration on updatedValue.

The correct answer is, no. There is no way to do anything to updatedValue without involving self. One way of doing it would be with Observable<Int>.interval(1, scheduler: MainScheduler.instance).compactMap { [weak self] _ in self?.updatedValue }.distinctUntilChanged() (Your use of publish and connect is odd and unnecessary,) but that involves self.

Since your property is a value type, the only way to access it is through self, even if Rx wasn't involved at all.