* 上篇文章简单的介绍了RAC简单的基础方法,这篇文章继续介绍另外的几个方法和分析一下在开发中的具体应用场景 *
除了前一篇的几个方法,还有一个很基本的方法,就是 filter:bolck,先做个小实验。借用上一篇的UITextField.
[[self.nameTextField.rac_textSignal filter:^BOOL(NSString *value) {
return value.length>2 && value.length < 7;
}] subscribeNext:^(id x) {
NSLog(@"x=%@",x);
}];
打印信息:
2016-03-26 12:42:36.517 RACDemo[1931:80934] x=112
2016-03-26 12:42:37.675 RACDemo[1931:80934] x=1122
2016-03-26 12:42:38.273 RACDemo[1931:80934] x=11223
2016-03-26 12:42:38.809 RACDemo[1931:80934] x=112233
可以清楚的看到,只有当我们输入的内容的长度在我们限制的范围内(2< 长度 <7)的时候,才会触发subscribeNext的信号。
如图所示
相当于我们在冷信号转化为热信号的途中加了条件限制,只有满足了条件,信号才会变热,才能被响应。
在开发过程中filter常用来对数组进行筛选,从一个数组里去掉我们不想要的数据。用传统的方法for循环肯定能够解决,但使用RAC会更加简洁。
NSArray *dataArray = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7"];
dataArray = [[[dataArray rac_sequence]filter:^BOOL(id value) {
return [value integerValue]>2&&[value integerValue]<6;
}] array];
打印日志:
2016-03-26 13:58:32.167 RACDemo[2585:171400]
(
3,
4,
5
)
经过上面的filter处理,我们可以看到成功的去除了数组里的几个元素,得到了一个我们想要的数组。除了filter,这里还有个陌生的字眼 rac_sequence,这是RAC为系统类NSArray添加的一个方法,把数组转化为RACSequence类型。
RAC中有两个比较重要的class , 一个是上篇文章提到的RACSignal,还有一个就是RACSequence,它和数组相似,可以用来保存数组或者字典里面的内容。经过条件过滤后,使用 array 方法把RACSequence类型又转化为Objective-c里面的NSArray。
这里补充一下filter 和 map的结合使用:
dataArray = [[[[dataArray rac_sequence]filter:^BOOL(id value) {
return [value integerValue]>2&&[value integerValue]<6;
}]map:^id(NSNumber *value) {
return @([value integerValue] + 2016);
}] array];
NSLog(@"%@",dataArray);
打印日志:
2016-03-26 14:08:48.208 RACDemo[2585:171400] (
2019,
2020,
2021
)
可以看到,在筛选完成后,我们还可以对RACSequence里的数据进行操作,转化为我们想要的数据。这也是RAC的魅力所在,block的嵌套让代码结构看起来更加紧凑,清爽。
说到map,不得不说一下相似的一个方法flattenMap。通过上篇文章,我们知道map的作用是信号转换器,
[self.nameTextField.rac_textSignal map:^id(NSString *text) {
return text.length>0?[UIColor blackColor]:[UIColor lightGrayColor];
}];
能通过自定义操作,把text信号转化为我们所需要的信号。具体内部实现还是会调用flattenMap。
通过map操作是在原来信号的基础上创建一个新的signal,这个新的signal是依赖于上一个的signal的,而flattenMap是直接创建了一个新的signal,和上一个signal没有关系。
代码是最有说服力的,现在举一个例子:
[[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] map:^id(id value) {
return value;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
打印日志:
2016-03-26 16:47:31.966 RACDemo[3961:313813] <UIButton: 0x7ffd49723340; frame = (23 269; 329 45); clipsToBounds = YES; opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7ffd49721830>>
对于打印结果,想必你早就知道了,这里打印的只是button的信息。
现在我去创建一个新的信号(下篇重点介绍信号的创建已接收)
RACSignal *new_signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"今天是个好日子"];
return nil;
}];
这个信号就一个作用,发送一个特定的字符串。
我能否在map:的block里面返回这样的一个信号呢?试试看
[[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] map:^id(id value) {
return new_signal;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
打印日志:
2016-03-26 16:50:13.249 RACDemo[4027:317010] <RACDynamicSignal: 0x7fb7635b8d00> name:
然而,并没有得到我们想要的那串字符串,这就是因为map只能在上个信号的基础上转换,下面我们换成flattenMap,看看效果如何:
[[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] flattenMap:^RACStream *(id value) {
return new_signal;
}]subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
打印日志:
2016-03-26 17:03:30.612 RACDemo[4133:331613] 今天是个好日子
ok,这也证实了上面说的flattenMap用于返回一个上个信号没有关系的新的信号。
总结:本文继续介绍了RAC的一些基本的用法,包含 filter: , filter与map的组合使用,RACSequence类以及map与flattenMap的区别。到这里上对信号的基本操作有了一定的能力。这时候或许你会有疑问,我如何去自己创建信号,发送信号,以及接受信号。下篇文章将详细描述。