I'm still new to ReactiveCocoa. I wanted to simply add an observer to a field, so did it like this:
[_countryPicker rac_observeKeyPath:@"value" options:nil observer:self block:^(VBCountry* value, NSDictionary* change)
{
if ([_mobileField.textField.text length] == 0)
{
[_mobileField.textField setText:[NSString stringWithFormat:@"+%i", value.dialCode]];
}
}];
With block callback, and no need to explicitly detach the observer, this is already better than old-style KVO.
However, is this a low-level method to which there's a higher level of abstraction? If so, is it OK to call this method directly? And what's the better/higher way to do it?
I'd advise against depending on the direct KVO methods. They're really an implementation detail.
Let's progressively re-write that with idiomatic RAC operators.
First we'll just replace the direct KVO code with RACObserve
:
[RACObserve(_countryPicker, value) subscribeNext:^(VBCountry *value) {
if ([_mobileField.textField.text length] == 0)
{
[_mobileField.textField setText:[NSString stringWithFormat:@"+%i", value.dialCode]];
}
}];
Then we'll replace the if
and string formatting with -filter:
and -map:
:
[[[RACObserve(_countryPicker, value) filter:^(id _) {
return [_mobileField.textField.text length] > 0;
}] map:^(VBCountry *value) {
return [NSString stringWithFormat:@"+%i", value.dialCode];
}] subscribeNext:^(NSString *text) {
[_mobileField.textField setText:text];
}];
Finally we'll use the RAC
macro to make the assignment over time explicit:
RAC(_mobileField.textField, text) = [[RACObserve(_countryPicker, value) filter:^(id _) {
return [_mobileField.textField.text length] > 0;
}] map:^(VBCountry *value) {
return [NSString stringWithFormat:@"+%i", value.dialCode];
}];