使用ReactiveCocoa的循环绑定,如何将一个值绑定到两个输入UI元素

使用ReactiveCocoa的循环绑定,如何将一个值绑定到两个输入UI元素

问题描述:

在iOS项目中,我必须实现一个视图控制器,该控制器允许使用滑块同时选择一个浮点值。它应该具有以下行为:使用ReactiveCocoa的循环绑定,如何将一个值绑定到两个输入UI元素

  • 每当大量在文本字段中键入,滑块应该更新它的价值的类型浮点数
  • 每当滑块拖动它应该与更新文本字段滑块值

目前的想法如下:

我在视图模型,实际值和值文本的两种propertys。 每当更新值时,我都会更新视图模型中的文本。 文本字段和滑块都只更改该值。 但是,然后我有一种'循环'依赖:文本字段更新视图模型值,它更新视图模型文本,它绑定到我们只输入值的文本字段。这会导致文本字段的错误行为。我试图解决isFirstResponder属性,这种方法效果更好,但似乎并不是最佳实践,加上它并不像预期的那样。 有没有办法将slider的enabledProperty绑定到文本字段的isFirstResponder?这也将在VC工作

绑定:

 layout.valueTextField.reactive.text <~ viewModel.valueText.map({ text in 
     if !self.layout.valueTextField.isFirstResponder { 
      return text 
     } 
     return self.layout.valueTextField.text ?? "" 
     } 
    ) 
    viewModel.value <~ layout.valueSlider.reactive.values 
    layout.valueSlider.reactive.value <~ viewModel.value 
    viewModel.value <~ layout.valueTextField.reactive.continuousTextValues.map({ textValue in 
     if let t = textValue { 
      if let parsed = Float(t) { 
       return parsed 
      } 
     } 
     return viewModel.value.value 
    }) 

我的看法型号:

import ReactiveSwift 

class ValuePickerViewModel { 

var valueText: MutableProperty<String> 
var value: MutableProperty<Float> 
let minValue: Float 
let maxValue: Float 
let unit: String 

init(initialValue: Float, formatter: FloatFormatter, minValue: Float, maxValue: Float, unit: String) { 
    self.value = MutableProperty(initialValue) 
    self.valueText = MutableProperty(formatter.format(value: initialValue)) 
    self.valueText <~ self.value.map({value in 
     formatter.format(value: value) 
     } 
    ) 
    self.minValue = minValue 
    self.maxValue = maxValue 
    self.unit = unit 
} 

} 

解决方法很简单: 的文本框的值绑定到视图模型浮点值。 幻灯片值绑定到视图模型文本值。 所以每个组件都更新其他组件,并且没有循环!

工作代码:

绑定:

viewModel.value <~ layout.valueTextField.reactive.continuousTextValues.map({ textValue in 
     if let t = textValue { 
      if let parsed = Float(t) { 
       return parsed 
      } 
     } 
    return viewModel.value.value 
    }) 
    viewModel.valueText <~ layout.valueSlider.reactive.values.map({ value in 
     return viewModel.formatter.format(value: value) 
    }) 
    layout.valueSlider.reactive.value <~ viewModel.value 
    layout.valueTextField.reactive.text <~ viewModel.valueText 

视图模型:

import ReactiveSwift 

class ValuePickerViewModel { 

var valueText: MutableProperty<String> 
var value: MutableProperty<Float> 
let minValue: Float 
let maxValue: Float 
let unit: String 
let formatter: FloatFormatter 

init(initialValue: Float, formatter: FloatFormatter, minValue: Float, maxValue: Float, unit: String) { 
    self.formatter = formatter 
    self.value = MutableProperty(initialValue) 
    self.valueText = MutableProperty(formatter.format(value: initialValue)) 
    self.minValue = minValue 
    self.maxValue = maxValue 
    self.unit = unit 
} 

}