我正在尝试使用ReactiveCocoa来控制应用中文本字段的绑定和验证。当我订阅信号时,它会立即从文本字段到模型进行绑定并运行验证。通常这不是问题,但在这种情况下,该字段是“密码”输入,其中模型的初始值不会被复制到文本字段。我希望绑定和验证仅在用户实际在字段中键入内容时触发。有谁知道这样做的方法?
以下是我目前正在做的事情:
- (void)setUpBindings: forModel:(NSObject<ValidationModel> *)model {
NSString *property = @"password"
NSInteger throttleTime = 1.5;
[[[self.textField.rac_textSignal distinctUntilChanged]
throttle:throttleTime]
subscribeNext:^(id x) {
NSLog([NSString stringWithFormat:@"Model: %@, Value: %@", [model valueForKey:property], x]);
[model setValue:x forKey:property];
}];
[self bindValidator:[model.validators objectForKey:property]];
}
- (RACSignal *) passwordIsValid {
@weakify(self);
return [[RACObserve(self,password) distinctUntilChanged]
map:^id (NSString *newPassword) {
@strongify(self);
NSArray *errors = [self validatePassword];
return errors;
}];
}
-(void)bindValidator:(RACSignal *)validator
{
if(validator != nil)
{
[[[validator doNext:^(NSArray *errors) {
if(errors.count > 0)
{
NSError *error = [errors firstObject];
self.errorString =error.localizedDescription;
}
else
{
self.errorString = @"";
}
}]
map:^id(NSArray *errors) {
return errors.count <=0 ? @(1) : nil;
}] subscribeNext:^(id x) {
self.isValid = !!x;
}];
}
}
答案 0 :(得分:0)
我找到了一个可能的解决方案。 ReactiveCocoa有一个rac_signalForControlEvents方法,允许您手动指定要观察的事件。使用它,我能够为我的文本字段的UIControlEventEditingChanged事件定义一个初始信号。然后,我在subscribeNext中移动了我的绑定和验证信号的设置,延迟了他们的订阅,直到从文本字段发送更改事件。我在OP中的设置方法如下所示:
- (void)setUpBindings:(NSString *)property forModel:(NSObject<ValidationModel> *)model {
NSInteger throttleTime = 1.5;
RACSignal *textChangeSignal = [[self.textField.rac_textSignal distinctUntilChanged]
throttle:throttleTime];
//wait to subscribe to the signal until the user actually makes changes to the field.
//the 'take:1' call ensures that the subscription only happens the first time the event
//is observed.
[[[self.textField rac_signalForControlEvents:UIControlEventEditingChanged]
take:1]
subscribeNext:^(id x) {
[self bindValidator:[model.validators objectForKey:self.reuseIdentifier]];
[textChangeSignal subscribeNext:^(id x) {
[model setValue:x forKey:property];
}];
}];
}
重要提示:请注意&#39;拍摄:1&#39;外链中的方法。你必须包括这个。没有那个电话,外部&#39; subscribeNext&#39;每次触发编辑事件时都会运行,从而导致同一目标和事件的多个订阅者。有关详细信息,请参阅:How do I create a ReactiveCocoa subscriber that receives a signal only once, then unsubscribes/releases itself?
我现在要打开这个。这种方式有效,但我确信必须有一种更清洁的方法。
答案 1 :(得分:0)
您可以使用以下内容:
@weakify(self);
RACSignal *validPasswordSignal = [self.passwordTextField.rac_textSignal map:^id(NSString *text) {
@strongify(self);
return @([self isValidPassword:text]);
}];
- (BOOL)isValidPassword:(NSString *)password
{
return ([password length] > 0);
}
您可以将isValidPassword中的条件更改为您想要的任何内容。