项目中有个小需求,文本框与按钮绑定.当文本框内容符合规则的时候,按钮才会可用.把判定条件修改一下,代码如下:
1 | RAC(self.loginButton,enabled) = [self.textFiled.rac_textSignal map:^id(NSString *value) { |
但是如果在发送请求之后,通过代码清除了文本框的内容,按钮并不会改变状态.
想到了, 应该是这个 rac_textSignal
出现问题了.
看一下它的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 - (RACSignal *)rac_textSignal {
@weakify(self);
return [[[[[RACSignal
defer:^{
@strongify(self);
return [RACSignal return:self];
}]
concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]]
map:^(UITextField *x) {
return x.text;
}]
takeUntil:self.rac_willDeallocSignal]
setNameWithFormat:@"%@ -rac_textSignal", self.rac_description];
}
几个关键词的解释:defer
: 将代码的创建推迟到信号被订阅concat
: 连接信号,第一个信号必须发送完成,第二个信号才会被激活map
: 映射,将信号内容转换takeUtil
: signalA takeUntil:signalB 当signalB激活之后,停止signalA 的订阅
其实主要的是, 这个 signal
是监听的: UIControlEventAllEditingEvents
. 那么也就是说对setter
方式不会触发信号
RACObserve
是一个常用的宏,我们都知道是监听属性值改变的.
1 | #define RACObserve(TARGET, KEYPATH) \ |
主要代码是:[target_ rac_valuesForKeyPath:@keypath(TARGET, KEYPATH) observer:self];
然后这个rac_valuesForKeyPath
的实现如下:
1 | - (RACSignal *)rac_valuesForKeyPath:(NSString *)keyPath observer:(__weak NSObject *)observer { |
主要代码:
1 | rac_valuesAndChangesForKeyPath:keyPath options:NSKeyValueObservingOptionInitial observer:observer] |
也就是这个是通过 KVO
实现的. 而 KVO
得实现是通过临时生成一个子类,并重写父类的 setter
方法.这个在官方文档中有说明:
1 | Key-Value Observing Implementation Details |
最终实现
了解了两者的实现,就可以很容易实现代码:
1 | RAC(self.loginButton,enabled) =[ [RACObserve(self.textFiled, text) merge:self.textFiled.rac_textSignal ] map:^id(NSString *value) { |