【问题标题】:Swift 2 RAC4 Merge UITextField Signal and UISwitch SignalSwift 2 RAC4 合并 UITextField 信号和 UISwitch 信号
【发布时间】:2016-05-11 23:15:30
【问题描述】:

我已经编写了代码的响应式命令版本:

widthTextField.rac_textSignal().subscribeNext { (val) in
    let multiplier = 0.2
    if var v = Double(val as! String){
        if(self.viewModel.proportionalBool.value){
            v *= multiplier
            self.heightTextField.text = String(v)
        }
    }
}

我的 ViewModel 中有三个 MutableProperties:Bool 类型的比例布尔、高度字符串和字符串类型的宽度字符串。

我的 ViewController 中也有一个对应的 UISwitch 和两个 UITextField。

我想学习的是有以下场景: 1. 如果 bool/switch 为 false,那么 heightString 应该保持不变 2.如果bool为真,那么heightString应该是一个值:widthString * multiplier

我知道我写的代码很糟糕。我想我应该使用 combineLatest 但我不知道如何将两个信号:UITextField 和 UISwitch 合并为一个产生信号。

谁能给我任何提示或简单的代码示例?

let boolSignal = proportionalSwitch.rac_newOnChannel()
let widthSignal = widthTextField.rac_textSignal()
let heightSignal = heightTextField.rac_textSignal()
...?

【问题讨论】:

    标签: ios swift merge reactive-cocoa reactive-cocoa-4


    【解决方案1】:

    我将假设您始终希望 ViewModel 中的 MutableProperties 始终具有正确的值。

    我还将使用REX (which will soon be a part of RAC anyway) 来实现更简单的 UI 绑定。

    假设这是你的 viewModel:

    final class ViewModel {
        let on = MutableProperty<Bool>(false)
        let width = MutableProperty<Double>(0.0)
        let height = MutableProperty<Double>(0.0)
    }
    

    第一部分是将开关和文本字段绑定到 viewModel 的 MutableProperties。

    前两个比较直接:

    viewModel.on <~ onSwitch.rex_on
    viewModel.width <~ widthTextField.rex_textSignal
        .map { Double($0) ?? 0 }
    

    注意:如果宽度文本字段的输入不是有效数字,我选择发送 0 作为宽度。根据您的需要,您可能希望以不同的方式处理这种情况,例如通过让widthheight 属性具有可选值...

    现在高度几乎相同,但我们必须确保它仅在开关打开时处理。这是通过使用combineLatestfilter 实现的:

    viewModel.height <~ combineLatest(viewModel.on.producer, viewModel.width.producer)  // SignalProducer<(Bool, Double), NoError>
        .filter { on, text in return on }   // Only send values when the switch is `on`
        .map { on, width in return width }  // Now we dont care about the switch value anymore, extract just the width
        .map { width in return 0.5 * width }// Transform the width as you wish
    

    现在,剩下的就是将高度的值绑定到 UI。除非我遗漏了什么,否则 REX 对此没有任何帮助(至少对于 UITextField 没有帮助),所以我们将不得不使用 DynamicProperty

    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Previously mentioned binding to the viewModel
    
        DynamicProperty(object: heightTextField, keyPath: "text") <~ viewModel.height.producer.map { String($0) }
    }
    

    【讨论】:

    • MeXx 太棒了!谢谢!
    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多