ios - 使用 ReactiveCocoa 将 UIKit 与 View 模型绑定(bind) 3/4

标签 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
}];

在 RC 3 或 4 中使用 Swift。就好像他们还没有对 UIKit 进行适当的扩展。

然后我想我也许可以做点什么 á la

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

View 模型具有此属性的地方:

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

它会打印出日期的变化。

编辑 3

此外,为了确保 View 模型属性也很好,我有这个:

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

viewModel.selectedDate = MutableProperty(NSDate())

它也按预期打印。

编辑 4

我的 View 模型如下所示:

class MainViewModel {
    var selectedDate: MutableProperty<NSDate>

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

还有我的 View Controller :

private var viewModel = MainViewModel()

最佳答案

错误的原因是因为你不能绑定(bind)一个可以发出错误的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

关于ios - 使用 ReactiveCocoa 将 UIKit 与 View 模型绑定(bind) 3/4,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34005109/

相关文章:

ios - 组合 RAC 信号并接收所有值

ios - 需要为 iCarousel 创建 NSIndexPath 以将信息传递给其他 View Controller

ios - react swift : How to write a Task Scheduler

iOS : refreshing already loaded tableView

ios - 模拟寿司火车 - Swift SpriteKit

ios - 取消 webView 后,webView 中嵌入的视频仍在播放 - iOS

ios - 如何防止在后续异步调用完成之前发送下一个事件的信号?

ios - 从 UITableView(不是 UITableViewController)转到 UIViewController

swift - 如何在按钮处于事件状态时重复生成 SKnode

objective-c - 在 ReactiveCocoa 中观察的更好方法