ios - 基于 UITextField 中文本的响应式(Reactive) Cocoa 启用按钮
<p><p>我在 Reactive Cocoa 中遇到了一些非常简单的代码问题,我不明白我做错了什么。 </p>
<p>我只是试图将 UIButton 的启用状态绑定(bind)到信号。该信号采用 <code>UITextField</code> 的文本并通过正则表达式运行它。这样我就可以在正则表达式匹配时启用按钮。</p>
<p>这段代码在加载 ViewController 时给了我一个异常:</p>
<pre><code>// 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);
];
@weakify(self);
[mySignal map:^(NSString *value) {
@strongify(self);
NSUInteger matches = [self.regex numberOfMatchesInString:value
options:0
range:NSMakeRange(0, )];
return @(matches > 0);
}];
RAC(self.continueButton, enabled) = mySignal;
</code></pre>
<p>很明显,异常说明我正在尝试从 <code>UITextField</code> 中“启用”选择器,而 <code>UITextField</code> 没有此选择器。我不明白为什么当我在 <code>continueButton</code> 而不是 <code>myTextField</code> 中调用启用的选择器时会出现此错误。</p>
<p>基本上异常(exception)是:</p>
<pre><code>: unrecognized selector sent to instance 0xa2c7830
</code></pre>
<p>调试器停在该行:</p>
<pre><code>;
</code></pre>
<p>实例 <code>0xa2c7830</code> 是一个 <code>UITextField</code>。 <code>object</code> 是 <code>UIButton</code> 而 <code>keyPath</code> 是 <code>@"enabled"</code>。我只是看不出这个设置有什么问题,除了它是在我的 <code>UITextField</code> 而不是 <code>UIButton</code> 上调用的!</p>
<p>感谢您的帮助!</p></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>提示在这里:</p>
<pre><code>
</code></pre>
<p>无法识别的选择器未<code>启用</code>;它是 <code>charValue</code>。好的,为什么我们要让 <code>UITextField</code> 变成 <code>char</code>?嗯...如果我们想将其转换为 bool 值,那么 KVO 机制可能会认为它是一个 <code>NSNumber</code> 并尝试将其视为这样。但它不是 <code>NSNumber</code> - 因此是异常(exception)。</p>
<p>但是等等,我们不是将信号映射为创建一个 <code>NSNumber</code> 吗?为什么我们首先要尝试将其转换为 bool 值?为什么它是 <code>UITextField</code> 而不是 <code>NSString</code>? (我们稍后再讨论)</p>
<p>啊。好吧,我们实际上并没有将信号映射到其他东西,因为 <code>map:</code> 没有破坏性。</p>
<p>我的意思是 <code>map:</code> <em>创建一个新信号</em>。它不会修改 <code>mySignal</code>。我们调用 <code>map:</code> 来创建一个新信号,但是我们从来没有对它做任何事情——它只是坐在那里,没有人订阅它,然后它就被释放了。但我们想订阅它!</p>
<pre><code>RAC(self.continueButton, enabled) = [mySignal map:^(NSString *value) {
@strongify(self);
NSUInteger matches = [self.regex numberOfMatchesInString:value
options:0
range:NSMakeRange(0, )];
return @(matches > 0);
}];
</code></pre>
<p>啊哈!现在我们将 <code>enabled</code> 属性绑定(bind)到转换后的信号——这正是我们一直想要的。但还是有些不对劲。</p>
<p>当我们尝试进行正则表达式匹配时会发生一些不好的事情......如果我不得不猜测 <code>: unrecognized selector sent to instance 0xWhatever</code></p>
<p><code>UITextField</code> 再次?那家伙怎么了?</p>
<p>这个问题的答案回到 <code>mySignal</code>。 <code>mySignal</code> <em>实际上</em> 发送什么?我们希望它发送文本...但如果我刚刚编写的新异常是正确的,它会发送一个 <code>UITextField</code>!为什么?那么,<code>mySignal</code> 是 <code>RACObserve(self, myTextField)</code>。可是等等!这将发送文本字段的新值——而不是文本字段文本的新值。你想要的是:</p>
<pre><code>RACSignal *mySignal = self.myTextField.rac_textSignal;
</code></pre>
<p>这将发送文本字段文本的新值,而不是文本字段的新值。</p>
<p>呸。那应该行得通。提示:<code>log*</code> 帮助器对于调试非常有用。</p>
<pre><code>RAC(self.continueButton, enabled) = ;
</code></pre>
<p>这会告诉你 <code>mySignal</code> 正在发送 <code>UITextField</code>s 而不是 <code>NSString</code>s。</p></p>
<p style="font-size: 20px;">关于ios - 基于 UITextField 中文本的响应式(Reactive) Cocoa 启用按钮,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/22845419/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/22845419/
</a>
</p>
页:
[1]