Validation ReactiveCocoa-观察isFirstResponder属性和UITextField,ClearOnBeginEdit设置为YES

Validation ReactiveCocoa-观察isFirstResponder属性和UITextField,ClearOnBeginEdit设置为YES,validation,uitextfield,reactive-cocoa,Validation,Uitextfield,Reactive Cocoa,我对ReactiveCocoa还不熟悉,但我认为它是一种非常好的降低代码复杂性的优秀技术。我刚刚开始体验这个框架,现在还不是所有的事情都很清楚,所以如果我的问题能够以某种明显的方式得到解决,请原谅 在我的应用程序中,我有一个简单表单的登录视图控制器,它包含两个文本字段(用户名和密码)和一个按钮。如果两个文本字段中的任何一个为空,我希望该按钮被禁用。所以,我写了这段代码: RAC(self.loginButton, enabled) = [RACSignal combineLatest:@[se

我对ReactiveCocoa还不熟悉,但我认为它是一种非常好的降低代码复杂性的优秀技术。我刚刚开始体验这个框架,现在还不是所有的事情都很清楚,所以如果我的问题能够以某种明显的方式得到解决,请原谅

在我的应用程序中,我有一个简单表单的登录视图控制器,它包含两个文本字段(用户名和密码)和一个按钮。如果两个文本字段中的任何一个为空,我希望该按钮被禁用。所以,我写了这段代码:

RAC(self.loginButton, enabled) = 
[RACSignal combineLatest:@[self.userTextField.rac_textSignal,
                           self.passwordTextField.rac_textSignal]
                  reduce:^(NSString *username,
                           NSString *password) {
                      BOOL valid = (username.length > 0 && password.length > 0);
                      return @(valid);
                  }];
这很简单,而且很有效。问题是,我的一个文本字段(密码字段)的
secureTextEntry
clearsOnBeginEditing
属性设置为YES。我将尝试解释我在此配置中遇到的不需要的行为:

假设用户名和密码字段都不是空的。在这种情况下,按钮处于启用状态。当用户点击密码字段时,它将成为第一响应者(出现键盘,用户可以输入密码),但由于该字段的
clearsOnBeginEditing
设置为YES,先前输入的密码将从文本字段中清除。这就是密码字段现在为空的方式。问题是没有发送信号,因此尽管密码字段为空,按钮仍保持启用状态

我解决这个问题的第一个想法(更像是变通解决方案)是在观察文本更改的同时,观察密码字段上的
isFirstResponder
属性。这就是当密码字段成为第一响应者时,检查按钮是否应启用的块将被调用的方式。我不知道这个解决方案是否有效,因为我不知道如何使用ReactiveCocoa实现它。我一直在寻找为
isFirstResponder
属性更改创建信号,但运气不好。这可能不是解决这个问题的最佳方法,但在这一点上我什么也没想到

然后,问题是:如何使用ReactiveCocoa观察
isFirstResponder
属性

还有一个更一般的问题:当
clearsOnBeginEditing
设置为YES时,如何观察文本字段的文本变化

更新:

我发现我可以为
uicontrolEventEditingDidBeagin
事件创建信号,该事件应该给我观察
isFirstResponder
属性更改的替代:

[self.passwordTextField rac_signalForControlEvents:UIControlEventEditingDidBegin]

不幸的是,这并不能解决问题。现在我了解到,字段在成为第一响应者后被清除,并且在成为第一响应者后自动清除字段不会发送文本更改信号。这样,当执行验证块时,它仍然认为密码字段不是空的,尽管密码字段已清除且为空,按钮仍保持启用状态。

不幸的是,
-rac\u textSignal
仅侦听
UIControlEventEditingChanged
。如果添加了
uicontrolEventEditingDidBeagin
,您将全部就绪

我想您可以将此修补到其中并提交一个拉取请求

-(RACSignal*)rac\u text信号{
@威克菲(自我);
返回[RACSignal]
推迟:^{
@强化(自我);
返回[RACSignal return:self];
}]
concat:[控制事件的自rac_信号:UIControlEventEditingChanged | uicontrolEventEditingDidBegen]]
映射:^(UITextField*x){
返回x.text;
}]
takeUntil:self.rac\u willdealocsignal]
setNameWithFormat:@“%@-rac_textSignal”,[self rac_description];
}

根据设计,在text属性上只观察到文本更改。之前已经讨论过此类拉取请求,但没有这样做的意图。查看我的问题了解更多详细信息:这不起作用,字段在成为第一响应者后被清除,并且在成为第一响应者后自动清除字段不会发送文本更改信号。首先,我会被告知编辑已经开始,然后(稍后)字段将被清除。不会工作吗?你试过了吗?我试过了,它似乎奏效了。由于某种原因,“编辑开始时清除”选项似乎会导致文本值在触发
uicontrolEventEditingDidBegen
事件之前更新。如果您记录这些值,您将看到该字段为空。@allprog我不确定该问题是否相同。您所说的是在程序更新之后接收
-rac\u textSignal
,而不是控制事件。这里我的建议是考虑一个额外的控制事件。这一点是要在需要时正确地获得更新的值——我会考虑“在开始编辑时清除”与用户和键盘驱动的实际文本变化一致。就好像用户用退格删除了整个字段。嘿,伙计们,仅供参考,以防你们需要它,它被合并到2.0主文件中。