Reputation: 45
I want to combine the rac_signalForControlEvent
on a UIButton with some combined textFields signals like so:
[[[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside]
combineLatestWith:textFieldsCombinedSignal]
filter:^BOOL(RACTuple *signals) {
return ((UIButton *)[signals first]).highlighted;
}] subscribeNext:^(RACTuple *signals) {
if ([signals.second boolValue])
{
[self doLogin];
}
else
{
[self error];
}
}];
But this way I have to filter for the button highlighted state otherwise the subscribeNext:
block is getting fired every time some of the textfields change (textFieldsCombinedSignal
).
I would love to achieve this without having to filter for the highlighted button's state (I'm using ReactiveCocoa to minimize state after all, and I don't feel like this is the proper way to do what I'm trying to do).
Upvotes: 0
Views: 454
Reputation: 6489
If you want a sequence of button tap and then the latest from your combined text field signal, it can be as simple as using -flattenMap:
:
[[[self.loginButton
rac_signalForControlEvents:UIControlEventTouchUpInside]
flattenMap:^(id _) {
return [textFieldsCombinedSignal take:1];
}]
subscribeNext:^…];
However, from what you've described, this seems like a classic case for RACCommand
. Both this code, and the original code, allow for the user to double tap the login button and trigger concurrent logins.
Before showing RACCommand
, I'll make a couple of assumptions about your code. From the name alone, textFieldsCombinedSignal
it could be a signal that sends a tuple of strings, but in your use it looks like it's actually a validation signal that sends YES/NO. I'll assume the latter and rename it to loginIsValid
. I'll also assume that -doLogin
is synchronous for the purpose of this example.
Now to RACCommand
:
self.loginButton.rac_command = [[RACCommand alloc] initWithEnabledSignal:loginIsValid signalBlock:^(id _) {
return [RACSignal defer:^{
[self doLogin];
return [RACSignal empty];
}];
}];
What this will do is enable/disable the login button based on the latest value sent on loginIsValid
. When enabled, a tap on the button will cause -doLogin
to be called, and the button will become disabled for the duration of the login process, preventing concurrent logins.
Upvotes: 1
Reputation: 6308
Sounds like you just want to sample the textFieldsCombinedSignal
whenever the button is tapped. Try using -sample:
:
RACSignal *buttonSignal = [self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside];
[[textFieldsCombinedSignal sample:buttonSignal] subscribeNext:^(RACTuple *combinedTextFields) {
// do stuff with combinedTextFields
}];
Upvotes: 1