How to subscribe on the value changed control event of a UISwitch Using Rxswift
Solution 1
I found the answer Im looking for, in order to subscribe on and control event we should do the below :
@IBOutlet weak var mySwitch : UISwitch!
mySwitch
.rx
.controlEvent(.valueChanged)
.withLatestFrom(mySwitch.rx.value)
.subscribe(onNext : { bool in
// this is the value of mySwitch
})
.disposed(by: disposeBag)
Solution 2
Below are some caveats you would use for UISwitch:
1. Make sure the event subscribes to unique changes so use distinctUntilChanged
2. Rigorous switching the switch can cause unexpected behavior so use debounce.
Example:
anySwitch.rx
.isOn.changed //when state changed
.debounce(0.8, scheduler: MainScheduler.instance) //handle rigorous user switching
.distinctUntilChanged().asObservable() //take signal if state is different than before. This is optional depends on your use case
.subscribe(onNext:{[weak self] value in
//your code
}).disposed(by: disposeBag)
Solution 3
There are couple of ways to do that. But this one is how I usually do it: Try this out.
self.mySwitch.rx.isOn.subscribe { isOn in
print(isOn)
}.disposed(by: self.disposeBag)
I hope this helps.
EDIT:
Another would be subscribing to the value
rx property of the UISwitch
, like so:
mySwitch.rx.value.subscribe { (isOn) in
print(isOn)
}.disposed(by: self.disposeBag)
Now, as for your comment:
this worked for me thanks , but I preferred subscribing on the control event it self, not the value.
We could do this below, I'm not sure though if there's a better way than this. Since UISwitch
is a UIControl
object, you can subscribe to its .valueChanged
event, like so:
mySwitch.rx.controlEvent([.valueChanged]).subscribe { _ in
print("isOn? : \(mySwitch.isOn)")
}.disposed(by: self.disposeBag)
More info: https://developer.apple.com/documentation/uikit/uiswitch
Solution 4
The following code works for me, building on prex's answer. Please feel free to correct or suggest any improvements.
RxSwift/RxCocoa 4.4, iOS 12, Xcode 10
private let _disposeBag = DisposeBag()
let viewModel: ViewModel ...
let switchControl: UIControl ...
let observable = switchControl
.rx.isOn
.changed // We want user-initiated changes only.
.distinctUntilChanged()
.share(replay: 1, scope: .forever)
observable
.subscribe(onNext: { [weak self] value in
self?.viewModel.setSomeOption(value)
})
.disposed(by: _disposeBag)
In this example, we are notified when the user (and only the user) changes the state of the UISwitch
. We then update viewModel
.
In turn, any observers of the viewModel
, will be told of the change of state, allowing them to update UI, etc.
e.g.
class ViewModel
{
private var _someOption = BehaviorRelay(value: false)
func setSomeOption(_ value: Bool) { _someOption.accept(value) }
/// Creates and returns an Observable on the main thread.
func observeSomeOption() -> Observable<Bool>
{
return _someOption
.asObservable()
.observeOn(MainScheduler())
}
}
...
// In viewDidLoad()
self.viewModel
.observeSomeOption()
.subscribe(onNext: { [weak self] value in
self?.switchControl.isOn = value
// could show/hide other UI here.
})
.disposed(by: _disposeBag)
MhmdRizk
Updated on June 24, 2022Comments
-
MhmdRizk almost 2 years
I want to use
Rxswift
and notIBActions
to solve my issue below,I have a
UISwitch
and I want to subscribe to the value changed event in it,I usually subscribe on Buttons using this manner
@IBOutlet weak var myButton: UIButton! myButton .rx .tapGesture() .when(.recognized) .subscribe(onNext : {_ in /*do action here */})
Does anyone know how to subscribe to
UISwitch
control events? -
MhmdRizk over 5 yearsthis worked for me thanks , but I preferred subscribing on the control event it self, not the value
-
MhmdRizk over 5 yearsthanks for the effort bro, but I posted the solution and it worked by subscribe on the value changed event, check my answer