Reputation: 1751
I have worked a lot with ReactiveCocoa 2.x.y
and am now playing with migrating to 4.0 (I know it's still in alpha as of this writing).
However, I have a difficult time figuring out how do this:
RAC(viewModel, selectedDate) = [[self.view.datePicker rac_signalForControlEvents:UIControlEventsValueChanged] map:^id(UIDatePicker *picker) {
return picker.date
}];
in RC 3 or 4 using Swift. It is as if they haven't yet made the appropriate extensions to UIKit.
I then figured I could maybe do something á 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
})
where the view model has this property:
var selectedDate: MutableProperty<NSDate>
but that gives all kinds of compiler errors:
Binary operator '<~' cannot be applied to operands of type 'MutableProperty<NSDate>' and 'SignalProducer<NSDate, NSError>'
So I have managed to get rid of compiler errors using this:
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
})
but none of this code is ever executed. It seems like the producer is not started correctly, since this does get executed:
_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)")
})
To make sure that everything else is working as intended I have this:
_mainView.datePicker.rac_signalForControlEvents(.ValueChanged).toSignalProducer().startWithNext { (x) -> () in
guard let datePicker = x as? UIDatePicker else { return }
print("\(datePicker.date)")
}
which prints out date changes just fint.
Further, to make sure the view model property is also fine, I have this:
viewModel.selectedDate.producer.startWithNext { (selectedDate) -> () in
print("Selected date: \(selectedDate)")
}
viewModel.selectedDate = MutableProperty(NSDate())
which also prints as expected.
My view model looks as follows:
class MainViewModel {
var selectedDate: MutableProperty<NSDate>
init() {
selectedDate = MutableProperty(NSDate())
}
}
And my view controller:
private var viewModel = MainViewModel()
Upvotes: 1
Views: 708
Reputation: 1743
The reason for the error is because you can't bind a producer
that can emit errors, you need to handle them first. Because this is a signal converted from RACSignal
there is no way of knowing if they can really be emitted, so what I would do is guard against that:
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
}
I'd recommend creating an operator in a SignalProducerType
extension to implement this, something like assumeNoErrors
.
Upvotes: 0