The hint is here:
[UITextField charValue]
The unrecognized selector isn't enabled
; it's charValue
. Okay, why would we be asking a UITextField
to turn into a char
? Well...if we wanted to cast it down to a boolean, then it's possible the KVO mechanics think it's an NSNumber
and try to treat it as such. But it's not an NSNumber
-- hence the exception.
But wait, didn't we map the signal to create an NSNumber
? Why are we trying to cast it down to a boolean in the first place? And why is it a UITextField
instead of an NSString
? (We'll come back to that later)
Ah. Well, we actually didn't map the signal into something else, because map:
isn't destructive.
By that I mean map:
creates a new signal. It doesn't modify mySignal
. We call map:
, creating a new signal, but then we never do anything with it -- it just sits there, and nothing subscribes to it, and then it's deallocated. But we want to subscribe to it!
RAC(self.continueButton, enabled) = [mySignal map:^(NSString *value) {
@strongify(self);
NSUInteger matches = [self.regex numberOfMatchesInString:value
options:0
range:NSMakeRange(0, [value length])];
return @(matches > 0);
}];
Aha! Now we're binding the enabled
property to the transformed signal -- which is what we wanted all along. But something is still amiss.
Something bad is going to happen when we try to do the regex match...if I had to guess [UITextField length]: unrecognized selector sent to instance 0xWhatever
UITextField
again? What's up with that guy?
The answer to that comes back to mySignal
. What is mySignal
actually sending? We want it to send text...but if that new exception I just made up is correct, it's sending a UITextField
! Why? Well, mySignal
is RACObserve(self, myTextField)
. But wait! That will send new values of the text field -- not new values of the text field's text. What you want is:
RACSignal *mySignal = self.myTextField.rac_textSignal;
That will send new values of the text field's text, instead of new values of the text field.
Phew. That should work. As a tip: the log*
helpers are very useful for debugging.
RAC(self.continueButton, enabled) = [mySignal logAll];
That'll show you that mySignal
is sending UITextField
s instead of NSString
s.