iOS MVVM与反应式Cocoa、UITextField返回信号和条件:如何改进我的代码

iOS MVVM与反应式Cocoa、UITextField返回信号和条件:如何改进我的代码,ios,objective-c,mvvm,reactive-cocoa,Ios,Objective C,Mvvm,Reactive Cocoa,我正在试图找到一种方法来改进我的代码,这对我来说还不够“反应性”,但效果很好。 我有一个UITextfield,当我点击textfield的return按钮时,我想发送一个信号(登录我的用户),但前提是满足一个条件(我有一个信号:registerIsAllowedSignal) 实际上,我在这个信号上有一个subscribe next,我更新了其中的BOOL registerIsAllowed,我在我的UITextfieldreturn按钮subscriberNext中手动检查registerI

我正在试图找到一种方法来改进我的代码,这对我来说还不够“反应性”,但效果很好。
我有一个
UITextfield
,当我点击textfield的return按钮时,我想发送一个信号(登录我的用户),但前提是满足一个条件(我有一个信号:registerIsAllowedSignal)

实际上,我在这个信号上有一个subscribe next,我更新了其中的BOOL registerIsAllowed,我在我的
UITextfield
return按钮subscriberNext中手动检查registerIsAllowed==true,在这种情况下,我发送一个调用我的register方法返回一个信号:
[self.loginViewModel register]

我想通过删除布尔值上的“if”来改进我的设计,并直接使用
注册表sallowedsignal
,但我真的不知道怎么做,我的流程是:
-我需要我的注册表SALLOWEDSIGNAL在他上次解雇时返回true
-我需要我的UITextField返回信号是最后一个返回true的信号

所以,如果有人对我如何改进这一点有线索的话,那就太好了,但是,如果你认为我的代码“反应性很强”,而我正在做一些过火的事情,请告诉我:)

谢谢

下面是我的实际代码示例:

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;
}];
后来:

[[[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);
        }];
    }
}];

根据应该发生什么或
[self.loginViewModel register]
返回什么,我可能会这样做:

@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];
    }];
需要注意的几件事:

  • 尽量避免副作用(例如使用
    subcribeext
    doNext
    等)
  • 避免使用自己的状态布尔-直接使用信号
  • 考虑将格式化作为
  • 尽量避免创建保留循环(在我的示例中,我使用宏
    @weakify
    @strongify

我假设
[self.loginViewModel寄存器]
正在返回一个我们需要开始的信号。不要执行
subscribeNext
,而是尝试将其与您想要执行的操作与信号结果相结合。在我的示例中,我将一些用户对象绑定到结果,但也可能是结果应该触发视图转换?要记住的关键是尽可能避免副作用。

它如何解决我的问题?寄存器的执行不再链接到按返回键。@Power78很抱歉,我的回答太快了。我现在更新了。我对RAC块中所有的
self
引用都不满意-它可能更纯粹。