使用ReactiveCocoa 3/4将UIKit与视图模型绑定

时间:2015-11-30 18:07:36

标签: ios swift reactive-cocoa

我在ReactiveCocoa 2.x.y上做了很多工作,现在我正在使用迁移到4.0(我知道在撰写本文时它仍处于alpha状态)。

然而,我很难搞清楚这是怎么做的:

RAC(viewModel, selectedDate) = [[self.view.datePicker rac_signalForControlEvents:UIControlEventsValueChanged] map:^id(UIDatePicker *picker) {
    return picker.date
}];
使用Swift在RC 3或4中

。好像他们还没有对UIKit进行适当的扩展。

然后我想我可能会做一些事情

viewModel.selectedDate <~ view.datePicker.rac_signalForControlEvents(.ValueChanged).toSignalProducer().map({ (x) -> NSDate in
    guard let datePicker = x as? UIDatePicker else { return NSDate() }
    return datePicker.date
})

视图模型具有此属性:

var selectedDate: MutableProperty<NSDate>

但这会产生各种编译器错误:

Binary operator '<~' cannot be applied to operands of type 'MutableProperty<NSDate>' and 'SignalProducer<NSDate, NSError>'

修改

所以我设法使用它来摆脱编译器错误:

viewModel.selectedDate <~ _mainView.datePicker.rac_signalForControlEvents(.ValueChanged).toSignalProducer()
.flatMapError({ (error) -> SignalProducer<AnyObject?, NoError> in
    return .empty
}).map({ (x) -> NSDate in
    guard let datePicker = x as? UIDatePicker else { return NSDate() }
    return datePicker.date
})

但是这些代码都没有执行过。看起来生产者没有正确启动,因为 执行了:

_mainView.datePicker.rac_signalForControlEvents(.ValueChanged).toSignalProducer()
.flatMapError({ (error) -> SignalProducer<AnyObject?, NoError> in
    return .empty
}).map({ (x) -> NSDate in
    guard let datePicker = x as? UIDatePicker else { return NSDate() }
    return datePicker.date
}).startWithNext({ (date) -> () in
    print("\(date)")
})

编辑2

为了确保其他一切按预期工作,我有这个:

_mainView.datePicker.rac_signalForControlEvents(.ValueChanged).toSignalProducer().startWithNext { (x) -> () in
    guard let datePicker = x as? UIDatePicker else { return }
    print("\(datePicker.date)")
}

打印日期更改只是fint。

编辑3

此外,为确保视图模型属性也正常,我有:

viewModel.selectedDate.producer.startWithNext { (selectedDate) -> () in
    print("Selected date: \(selectedDate)")
}

viewModel.selectedDate = MutableProperty(NSDate())

也按预期打印。

编辑4

我的视图模型如下所示:

class MainViewModel {
    var selectedDate: MutableProperty<NSDate>

    init() {
        selectedDate = MutableProperty(NSDate())
    }
}

我的视图控制器:

private var viewModel = MainViewModel()

1 个答案:

答案 0 :(得分:0)

错误的原因是因为您无法绑定可能发出错误的producer,您需要先处理它们。因为这是从RACSignal转换而来的信号,所以无法知道它们是否真的可以被释放,所以我要做的是防范:

viewModel.selectedDate <~ view.datePicker
       .rac_signalForControlEvents(.ValueChanged)
       .toSignalProducer()
       .map { x -> NSDate in
            guard let datePicker = x as? UIDatePicker else { return NSDate() }
            return datePicker.date
       }
       .flatMapErrors { error -> SignalProducer<NSDate, NoError> in
           fatalError("Unexpected error: \(error)")

           return .empty
     }

我建议在SignalProducerType扩展名中创建一个运算符来实现此操作,例如assumeNoErrors