Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get change the value of the UISlider

Tags:

swift

rx-swift

How to get the values while moving the UISlider?

I'm using the following code:

ViewModel:

import Foundation
import RxSwift

final class ViewModel {

    private let disposeBag = DisposeBag()

    var value: Variable<Float>

    init() {

        self.value = Variable(Float(0.0))

    }
}

ViewController:

@IBOutlet var slider: UISlider!

private var viewModel: ViewModel!
private let disposeBag = DisposeBag()

override func viewDidLoad() {
    viewModel = ViewModel()

    slider.rx.value
        .subscribe(onNext: { (value) in
            self.viewModel.value = Variable(Float(value))
        })
        .addDisposableTo(disposeBag) 
}

But this code does not work. What's my mistake?

like image 724
Nick Avatar asked Oct 26 '25 03:10

Nick


2 Answers

You're replacing the Variable instead of inserting a new value into it. This is guaranteed to fail.

ViewModel.value should be a let instead of a var. You don't want to replace Variable, you want to assign a new value into it. While you are at it, make your ViewModel a struct:

struct ViewModel {
    let value = Variable<Float>(0)
}

It can be a final class if you must, but value should still be a let not a var.

Your viewDidLoad should look like this:

public override func viewDidLoad() {
    super.viewDidLoad()

    slider.rx.value
        .subscribe(onNext: { [weak self] value in
            self?.viewModel.value.value = value
        })
        .disposed(by: disposeBag)
}

Or better yet:

public override func viewDidLoad() {
    super.viewDidLoad()

    slider.rx.value
        .bind(to: viewModel.value)
        .disposed(by: disposeBag)
}

Or even better... Whatever is subscribing to ViewModel.value should subscribe/bind directly to slider.rx.value instead. That way you can get rid of the middleman.

Something like this:

public class ViewController: UIViewController {

    @IBOutlet weak var slider: UISlider!
    @IBOutlet weak var label: UILabel!
    
    private let disposeBag = DisposeBag()
    
    public override func viewDidLoad() {
        super.viewDidLoad()

        slider.rx.value
            .map { "The slider's value is \($0)" }
            .bind(to: label.rx.text)
            .disposed(by: disposeBag)
    }

}

You will see the label's text change as you move the slider.

like image 89
Daniel T. Avatar answered Oct 28 '25 23:10

Daniel T.


Not tested, but I would try:

override func viewDidLoad() {
    viewModel = ViewModel()

    slider.rx.value
        .subscribe(onNext: { (value) in
            self.viewModel.value.value = Float(value) 
        })
        .addDisposableTo(disposeBag) 
}

Also I would rename your value property in your viewModel to sliderValue (or whatever, but not value). If you do this, your code will look better:

self.viewModel.sliderValue.value = Float(value)

instead of

self.viewModel.value.value = ...

like image 37
xandrefreire Avatar answered Oct 28 '25 23:10

xandrefreire