How to subscribe on the value changed control event of a UISwitch Using Rxswift

13,004

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)

See: https://stackoverflow.com/a/53479618/1452758

Share:
13,004
MhmdRizk
Author by

MhmdRizk

Updated on June 24, 2022

Comments

  • MhmdRizk
    MhmdRizk almost 2 years

    I want to use Rxswift and not IBActions 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
    MhmdRizk over 5 years
    this worked for me thanks , but I preferred subscribing on the control event it self, not the value
  • MhmdRizk
    MhmdRizk over 5 years
    thanks for the effort bro, but I posted the solution and it worked by subscribe on the value changed event, check my answer