Reputation: 606
I'm new to using RxSwift framework, I'm actually learning and trying to understand the basics and I would like some help from you please.
private func observeCurrentIndex() -> Observable<Int> {
return Observable<Int>.create { (observer) -> Disposable in
observer.onNext(self.currentIndex)
return Disposables.create()
}
}
Here I've created an observable on currentIndex which is an int. When I subscribe to it, I get only the first value of currentIndex which is 2. Is it not supposed to notify me whenever currentIndex changes(just like a KVO would)?
override func viewDidLoad() {
super.viewDidLoad()
observeCurrentIndex()
.subscribe(onNext: { (valeur) in
print("new value \(valeur)")
})
.addDisposableTo(disposeBag)
}
To be notified each time currentIndex changes value, I've been told that I have to use a publishSubject for that.
@IBAction func increaseAction(_ sender: UIButton) {
if currentIndex <= kMaxIndex {
currentIndex = currentIndex + 1
}
}
Could someone indicate to me where and how to do this? Thanks in advance.
Upvotes: 0
Views: 5141
Reputation: 13661
Usually, Subject
s are used to bridge an imperative API to reactive world. More information on how to use subject can be found here.
There are a couple solution to observe a variable evolution using RxSwift's primitives
class WithIndex: NSObject {
dynamic var currentIndex: Int
func observeCurrentIndex() -> Observable<Int> {
return instance.rx.observe(Int.self, "currentIndex")
}
@IBAction func increaseAction(_ sender: UIButton) {
if currentIndex <= kMaxIndex {
currentIndex = currentIndex + 1
}
}
}
The drawback with this solution is that WithIndex
needs to inherit from NSObject
for KVO to be available.
class WithIndex {
let currentIndex: Variable<Int>
func observeCurrentIndex() -> Observable<Int> {
return currentIndex.asObservable()
}
@IBAction func increaseAction(_ sender: UIButton) {
if currentIndex.value <= kMaxIndex {
currentIndex.value = currentIndex.value + 1
}
}
}
This one is more pratical. You can then set currentIndex
's value using currentIndex.value = 12
and observe using currentIndex.asObservable().subscribe(...)
.
Variable
is a simple wrapper around BehaviorSubject
and will send a .next
event every time variable's value changes.
Upvotes: 2
Reputation: 3409
I come from RxJS, but I think what you really need is a ReplaySubject
.
The first code you provided, you're just creating an observable that only returns 1 value. The code inside Observable.create
just gets executed once every time someone .subscribe()
s on it.
A publish is more meant to share a subscription between many subscribers... The perfect case for that is that if you need a specific info gathered from one server to be used in many places in your app... You don't want to spam the server with so many requests, so you just make one request, publish that and observers will subscribe to that published stream.
A ReplaySubject (or BehaviourSubject, but then you need to know the initial value when you initialize it) is more in the line of what you want: It's both an Observable and an Observer, an object where other observers can subscribe to, and every time you call .onNext()
to it, all subscribers will get a new value.
Rx can't do magic, it doesn't know when/how you are editing your variables. So you will need to create a ReplaySubject
of length 1 in your object, and return that to subscribers. Then track on your code whenever your currentIndex
changes, call the onNext
method on that ReplaySubject.
Upvotes: 0