Marina Marina - 6 months ago 142
Swift Question

How to observe Bool properties with RxSwift?

I have two Bool properties in my VC.swift:

var isRecording = false
var isPlaying = false


In the viewDidLoad() method I have such code:

let observable = Observable.combineLatest(self.rx_observe(Bool.self, "isRecording"), self.rx_observe(Bool.self, "isPlaying")) { (val1, val2) -> Void in
if(val1 == false && val2 == false){
self.recordButton.enabled = true
self.playButton.enabled = true
self.recordButton.setImage(UIImage(named: "record"), forState: UIControlState.Normal)
self.playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
} else if(val1 == true && val2 == false){
self.recordButton.enabled = true
self.recordButton.setImage(UIImage(named: "stop"), forState: UIControlState.Normal)
self.playButton.enabled = false
} else if(val1 == false && val2 == true){
self.recordButton.enabled = false
self.playButton.enabled = true
self.playButton.setImage(UIImage(named: "stop"), forState: UIControlState.Normal)
self.recordButton.setImage(UIImage(named: "record"), forState: UIControlState.Normal)
}
}.observeOn(MainScheduler.instance)
addSubscription(observable.subscribe())


The function addSubscription(:_) adds subscription to DisposableBag.
The problem is that the code in the closure works only once. It does not work when properties "isRecording" and "isPlaying" change. What should I do if I want this code to be performed after I have these bool properties changed?

Answer

Don't use Bool and rx_observe. Instead, use a Subject such as Variable<Bool>.

let isRecording = Variable(false)
let isPlaying = Variable(false)

let observable = Observable.combineLatest(isRecording.asObservable(), isPlaying.asObservable()) { (val1, val2) -> Void in
    //...

However, to answer your question as to why it doesn't work with rx_observe, it's because rx_observe relies on the property being KVO compliant. If you used the dynamic keyword in front of your property definitions, it would have worked: dynamic var isRecording = false. However, you should really be using a Subject such as Variable. Check out the playground page dealing with Subjects in the RxSwift repo. It gives an example of each type.