I am trying to find a way to improve my code, it is not enough "Reactive" for me, but it works well.
I have a UITextfield
and I want to send a signal (Log in my user) when I click on the the return button of the textfield, but only if a condition is met (I have a signal for that : registerIsAllowedSignal).
Actually I have a subscribe next on this signal, and I update a BOOL registerIsAllowed in it, and I have a manual check in my UITextfield
return button subscribeNext to see if the registerIsAllowed == true, and in this case, I send a call my register method returning a signal : [self.loginViewModel register]
.
I would like to improve my design by removing the "if" on the boolean, and directly using the registerIsAllowedSignal
, but don't really know how to do it, my flow is :
- I need my registerIsAllowedSignal to have had return true the last he fired
- I need my UITextField return signal to have been the last to return true
So if anybody has leads on how I could improve that, it would be great, but also, if you think that my code is "Reactive enough" and I'm doing to do overkill stuff, please tell me :).
Thanks
Here is my actual code sample doing that :
self.logInAllowedSignal = [[RACSignal combineLatest:@[self.usernameIsValid, self.emailIsValid]] and];
[self.logInAllowedSignal subscribeNext:^(NSNumber *value) {
self.logInAllowed = value.boolValue;
}];
self.registerAllowedSignal = [[RACSignal combineLatest:@[self.logInAllowedSignal, self.passwordIsValid]] and];
[self.registerAllowedSignal subscribeNext:^(NSNumber *value) {
self.registerAllowed = value.boolValue;
}];
and later :
[[[tmpView.passwordTextField rac_keyboardReturnSignal] doNext:^(id x){
[tmpView.usernameTextField resignFirstResponder];
}]
subscribeNext:^(id x) {
@strongify(self);
if (self.registerAllowed)
{
[[self.loginViewModel register] subscribeNext:^(id x) {
NSLog(@"Register response : %@", x);
}];
}
}];
Depending on what should happen or what [self.loginViewModel register]
returns, I would probably do something like this:
@weakify(self);
self.logInAllowedSignal = [[RACSignal
combineLatest:@[self.usernameIsValid, self.emailIsValid]]
and];
self.registerAllowedSignal = [[RACSignal
combineLatest:@[self.logInAllowedSignal, self.passwordIsValid]]
and];
RAC(self, someUserObject) = [[[[[tmpView.passwordTextField rac_keyboardReturnSignal]
// resignFirstResponder uses side-effects so we can't avoid the doNext.
doNext:^(id _) {
[tmpView.usernameTextField resignFirstResponder];
}]
flattenMap:^RACStream *(id _) {
@strongify(self);
return self.registerAllowedSignal;
}]
filter:^BOOL(NSNumber *allowedToRegister) {
return [allowedToRegister boolValue];
}]
flattenMap:^RACStream *(id _) {
@strongify(self);
return [self.loginViewModel register];
}];
Few things to notice:
subcribeNext
, doNext
etc.)@weakify
and @strongify
).I assume that the [self.loginViewModel register]
is returning a signal which we need to get started. Instead of doing a subscribeNext
, try to combine it with what you want to do with the result of the signal. In my example I'm binding some user object to the result, but it could also be that the result should trigger a view transition? The key thing to remember is to avoid side-effects when possible.