ios - 基于 UITextField 中文本的响应式(Reactive) Cocoa 启用按钮

标签 ios objective-c reactive-cocoa

我在 Reactive Cocoa 中遇到一些非常简单的代码的问题,我不明白我做错了什么。

我只是想将 UIButton 的启用状态绑定(bind)到信号。该信号获取 UITextField 的文本并通过正则表达式运行它。这样我就可以在正则表达式匹配时启用该按钮。

这段代码在加载 View Controller 时给了我一个异常:

// Poperties used in the view controller
@property (strong, nonatomic) NSRegularExpression *regex;
@property (weak, nonatomic) IBOutlet UITextField *myTextField;
@property (weak, nonatomic) IBOutlet UIButton *continueButton;

// ... other stuff ...

// Code in my "view did load" method
RACSignal *mySignal = RACObserve(self, myTextField);

[mySignal deliverOn:[RACScheduler mainThreadScheduler]];

@weakify(self);
[mySignal map:^(NSString *value) {
    @strongify(self);
    NSUInteger matches = [self.regex numberOfMatchesInString:value
                                                     options:0
                                                     range:NSMakeRange(0, [value length])];
    return @(matches > 0);
}];

RAC(self.continueButton, enabled) = mySignal;

显然,该异常解释了我正在尝试从 UITextField 中“启用”选择器,而 UITextField 没有此选择器。我不明白为什么当我在 continueButton 中调用启用的选择器时会收到此错误,而不是 myTextField

基本上异常(exception)是:

[UITextField charValue]: unrecognized selector sent to instance 0xa2c7830

调试器停在该行:

[object setValue:x ?: nilValue forKeyPath:keyPath];

实例0xa2c7830是一个UITextFieldobject 是一个UIButtonkeyPath@"enabled"。我只是没有发现此设置有任何问题,除了它是在我的 UITextField 而不是 UIButton 上调用的!

感谢您的帮助!

最佳答案

提示在这里:

[UITextField charValue]

无法识别的选择器未启用;它是charValue。好的,为什么我们要要求 UITextField 转换为 char ?好吧...如果我们想将其转换为 bool 值,那么 KVO 机制可能会认为它是一个 NSNumber 并尝试将其视为这样。但它不是一个 NSNumber ——因此是异常(exception)。

但是等等,我们不是映射信号来创建 NSNumber 吗?为什么我们首先要尝试将其转换为 bool 值?为什么它是 UITextField 而不是 NSString? (我们稍后再讨论)

啊。好吧,我们实际上没有将信号映射到其他东西,因为 map: 不具有破坏性。

我的意思是map:创建一个新信号。它不会修改 mySignal。我们调用map:,创建一个新信号,但随后我们不会对它做任何事情——它只是坐在那里,没有任何人订阅它,然后它就被释放了。但我们想订阅它!

RAC(self.continueButton, enabled) = [mySignal map:^(NSString *value) {
    @strongify(self);
    NSUInteger matches = [self.regex numberOfMatchesInString:value
                                                     options:0
                                                     range:NSMakeRange(0, [value length])];
    return @(matches > 0);
}];

啊哈!现在我们将 enabled 属性绑定(bind)到转换后的信号上——这正是我们一直想要的。但还是有些不对劲。

当我们尝试进行正则表达式匹配时,将会发生一些不好的事情...如果我不得不猜测[UITextField length]:无法识别的选择器发送到实例0xWhatever

再次

UITextField?那个人怎么样了?

答案回到mySignalmySignal 实际上发送什么?我们希望它发送文本...但是如果我刚刚编写的新异常是正确的,它会发送一个 UITextField!为什么?嗯,mySignalRACObserve(self, myTextField)。可是等等!这将发送文本字段的新值——而不是文本字段文本的新值。你想要的是:

RACSignal *mySignal = self.myTextField.rac_textSignal;

这将发送文本字段文本的新值,而不是文本字段的新值。

唷。那应该有效。提示:log* 帮助器对于调试非常有用。

RAC(self.continueButton, enabled) = [mySignal logAll];

这将显示 mySignal 正在发送 UITextField 而不是 NSString

关于ios - 基于 UITextField 中文本的响应式(Reactive) Cocoa 启用按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22845419/

相关文章:

ios - UITextView 具有自定义字体和大小的 HTML 内容

ios - UIScrollView 取消 UIPageViewController 滚动时的手势

objective-c - iOS从文本框中解析和int并将其分配给要用于求和的整数值?

ios - 远程通知未按预期工作

iphone - dictionaryWithContentsOfFile 从我的属性列表文件中返回 nil

swift3 - ReactiveSwift - 更新 MutableProperty 的值?

ios - 如何让两个自定义 UICollectionViewCell 类共享相同的变量名

ios - 将 Storyboard 中的颜色值关联到枚举或结构

ios - ReactiveCocoa 无法识别的选择器

mvvm - Realm 和 react 性 cocoa