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];
}];
注意事项:
- 尽量避免副作用(例如使用
subcribeNext
、doNext
等)
- 避免使用您自己的状态布尔值 - 直接使用信号。
- 考虑将格式设置为 proposed by the authors
- 尽量避免创建保留循环(在我的示例中,我使用宏
@weakify
和 @strongify
)。
我假设 [self.loginViewModel register]
正在返回我们需要开始的信号。不要做 subscribeNext
,而是尝试将它与你想对信号结果做的事情结合起来。在我的示例中,我将一些用户对象绑定到结果,但结果也可能触发视图转换?要记住的关键是尽可能避免副作用。
我正在努力寻找一种方法来改进我的代码,这对我来说还不够"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];
}];
注意事项:
- 尽量避免副作用(例如使用
subcribeNext
、doNext
等) - 避免使用您自己的状态布尔值 - 直接使用信号。
- 考虑将格式设置为 proposed by the authors
- 尽量避免创建保留循环(在我的示例中,我使用宏
@weakify
和@strongify
)。
我假设 [self.loginViewModel register]
正在返回我们需要开始的信号。不要做 subscribeNext
,而是尝试将它与你想对信号结果做的事情结合起来。在我的示例中,我将一些用户对象绑定到结果,但结果也可能触发视图转换?要记住的关键是尽可能避免副作用。