场景1:界面有多个网络请求,当所有网络请求都完成时,才能展示界面。
- (void)viewDidLoad {
[super viewDidLoad];
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// requestA()
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:3.0];
[subscriber sendNext:@"网络A加载完成"];
});
return [RACDisposable disposableWithBlock:^{
NSLog(@"取消A信号");
}];
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// requestB()
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:5.0];
[subscriber sendNext:@"网络B加载完成"];
});
return [RACDisposable disposableWithBlock:^{
NSLog(@"取消B信号");
}];
}];
[self rac_liftSelector:@selector(responseA:B:) withSignalsFromArray:@[signalA, signalB]];
}
- (void)responseA:(id)a B:(id)b {
NSLog(@"%@, %@", a, b);
}
场景2:当一个界面有多个UITextField和UIButton选项,只有所有的UITextField都有值时UIButton才能可以点击。
- (void)viewDidLoad {
[super viewDidLoad];
[self rac_liftSelector:@selector(responseA:B:) withSignalsFromArray:@[self.textField1.rac_textSignal, self.textField2.rac_textSignal]];
}
- (void)responseA:(NSString *)str1 B:(NSString *)str2 {
if(![str1 isEqualToString:@""] && ![str2 isEqualToString:@""]) {
self.btn.enabled = YES;
} else {
self.btn.enabled = NO;
}
}
尤其是第二个场景,当一个界面有多个UITextField时,如果想监听UITextField的输入,再判断UIButton是否enable,不用RAC的话写起来是非常麻烦的。而且代码很乱,不好维护。使用RAC代码简洁好多倍,而且RAC还支持map(改变输出值)、filter(依据条件筛选输出值),在swift中用惯了这几个高阶函数,现在回过头来写OC,真的好不习惯。
[[self.textField1.rac_textSignal map:^id(id value) {
return [NSString stringWithFormat:@"%@--%@", [NSDate date], value];
}] delay:1.0];
[self.textField1.rac_textSignal filter:^BOOL(NSString *str) {
return str.length > 6;
}];
还可以delay发送信号,感觉可以抛弃之前用的BlocksKit了,RAC功能完全可以取代。
翻看了一下UITextField的RAC分类,里面用到了大量底层代码,不过我的大概思路应该是先用对象关联为textField保存已个类,然后该类成为textField的代理,实现动态添加textViewDidChange方法,当textField的text改变时,则回调block,当然这个block也用对象关联保存起来了。 当然这只是一个大体思路,真正的实现肯定不止这么简单。