iOS 带有 Reactive Cocoa、UITextField return 信号和条件的 MVVM:如何改进我的代码

iOS MVVM with Reactive Cocoa, UITextField return signal and condition : how to improve my code

我正在努力寻找一种方法来改进我的代码,这对我来说还不够"Reactive",但效果很好。
我有一个 UITextfield 并且我想在单击文本字段的 return 按钮时发送一个信号(登录我的用户),但前提是满足条件(我有一个信号那:registerIsAllowedSignal).

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

我想通过删除布尔值上的 "if" 并直接使用 registerIsAllowedSignal 来改进我的设计,但我真的不知道该怎么做,我的流程是 :
- 我需要我的 registerIsAllowedSignal 在他最后一次解雇时 return 为真
- 我需要我的 UITextField return 信号是最后一个 return true

因此,如果有人知道我如何改进它,那就太好了,而且,如果您认为我的代码是 "Reactive enough" 并且我正在做一些过分的事情,请告诉我:).

谢谢

这是我执行此操作的实际代码示例:

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] returns,我可能会这样做:

@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];
    }];

注意事项:

  • 尽量避免副作用(例如使用 subcribeNextdoNext 等)
  • 避免使用您自己的状态布尔值 - 直接使用信号。
  • 考虑将格式设置为 proposed by the authors
  • 尽量避免创建保留循环(在我的示例中,我使用宏 @weakify@strongify)。

我假设 [self.loginViewModel register] 正在返回我们需要开始的信号。不要做 subscribeNext,而是尝试将它与你想对信号结果做的事情结合起来。在我的示例中,我将一些用户对象绑定到结果,但结果也可能触发视图转换?要记住的关键是尽可能避免副作用。