如何更改UISlider的值

时间:2017-07-16 17:02:31

标签: swift rx-swift

如何在移动UISlider时获取值?

我正在使用以下代码:

视图模型:

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) 
}

但是这段代码不起作用。我的错是什么?

3 个答案:

答案 0 :(得分:5)

您正在替换变量而不是在其中插入新值。这保证会失败。

ViewModel.value应该是let而不是var。您不想替换变量,您想要将新值分配到中。当你在它时,使你的ViewModel成为一个结构:

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

如果必须,可以是最后一堂课,但value应该仍然是let而不是var

您的viewDidLoad应如下所示:

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

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

或者更好:

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

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

甚至更好......订阅ViewModel.value的任何东西都应该直接订阅/绑定到slider.rx.value。这样你就可以摆脱中间人。

这样的事情:

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)
    }

}

移动滑块时,您会看到标签的文字发生变化。

答案 1 :(得分:4)

未经测试,但我会尝试:

override func viewDidLoad() {
    viewModel = ViewModel()

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

另外,我会将value中的viewModel属性重命名为sliderValue(或其他,但不是value)。如果这样做,您的代码看起来会更好:

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

而不是

self.viewModel.value.value = ...

答案 2 :(得分:2)

如果您使用新的BehaviorRelay而不是旧的Variable

struct MyViewModel {
    let value = BehaviorRelay<Float>(value: 0)
}

class ViewController: UIViewController {
    @IBOutlet var slider: UISlider!
    @IBOutlet var valueLabel: UILabel!
    private var viewModel = MyViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()

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

        // If you want to listen and bind to a label
        viewModel.value.asDriver()
            .map { "Value: \($0 * 100)%" }
            .drive(valueLabel.rx.text)
            .disposed(by: rx.disposeBag)
    }
}