RAC 知识点整理 - 2 ~ 持续更新

(一)只取所需的Filters

本段主要介绍RAC消息流的过滤器-Filters类别的相关方法
 
RAC中的Filters
画个范围
一个Signal源可以产生一系列next值,但并非所有值都是需要的,具体的Subscriber可以选择在原有Signal上套用Filter操作来过滤掉不需要的值。
 
我的定义:RAC中如果一个Operation将处理后的值集合是处理前值集合的子集,我们就可以把它归为Filter类型。
 
当然通过之前介绍的基础操作完全可以自己拼出个想要的filter来,RAC为了方便使用已经实现了几个常用的filter,经过总结,这些filter大概可以分成两类:next值过滤类型和起止点过滤类型。
 
值过滤类型Filters
 
- filter: (BOOL (^)(id value))
RAC中的filter同名方法- filter:(BOOL (^)(id value)),简单明了,将一个value用block做test,返回YES的才会通过,它的内部实现使用了- flattenMap:,将原来的Signal经过过滤转化成只返回过滤值的Signal,用法也不难理解:
 
  
  1. [[self.inputTextField.rac_textSignal filter:^BOOL(NSString *value) { 
  2.     return [value hasPrefix:@"sunny"]; 
  3. }] subscribeNext:^(NSString *value) { 
  4.     NSLog(@"This value has prefix `sunny` : %@", value); 
  5. }]; 
 
此外,还有几个这个方法的衍生方法:
 
- ignore: (id) 
忽略给定的值,注意,这里忽略的既可以是地址相同的对象,也可以是- isEqual:结果相同的值,也就是说自己写的Model对象可以通过重写- isEqual:方法来使- ignore:生效。常用的值的判断没有问题,如下:
 
  
  1. [[self.inputTextField.rac_textSignal ignore:@"sunny"] subscribeNext:^(NSString *value) { 
  2.     NSLog(@"`sunny` could never appear : %@", value); 
  3. }]; 
 
- ignoreValues
这个比较极端,忽略所有值,只关心Signal结束,也就是只取Comletion和Error两个消息,中间所有值都丢弃。
 
注意,这个操作应该出现在Signal有终止条件的的情况下,如rac_textSignal这样除dealloc外没有终止条件的Signal上就不太可能用到。
 
- distinctUntilChanged
也是一个 相当常用的Filter(但它不是- filter:的衍生方法),它将这一次的值与上一次做比较,当相同时(也包括- isEqual:)被忽略掉。
 
比如UI上一个Label绑定了一个值,根据值更新显示的内容:
 
  
  1. RAC(self.label, text) = [RACObserve(self.user, username) distinctUntilChanged]; 
  2. self.user.username = @"sunnyxx"// 1st 
  3. self.user.username = @"sunnyxx"// 2nd 
  4. self.user.username = @"sunnyxx"// 3rd 
 
如果不增加distinctUntilChanged的话对于连续的相同的输入值就会有不必要的处理,这个栗子只是简单的UI刷新,但遇到如写数据库,发网络请求的情况时,代价就不能购忽略了。
 
所以,对于相同值可以忽略的情况,果断加上它吧。
 
起止点过滤类型
除了被动的当next值来的时候做判断,也可以主动的提前选择开始和结束条件,分为两种类型:take型(取)和 skip型(跳)
 
- take: (NSUInteger)
从开始一共取N次的next值,不包括Competion和Error,如:
 
  
  1. [[[RACSignal createSignal:^RACDisposable *(id subscriber) { 
  2.     [subscriber sendNext:@"1"]; 
  3.     [subscriber sendNext:@"2"]; 
  4.     [subscriber sendNext:@"3"]; 
  5.     [subscriber sendCompleted]; 
  6.     return nil; 
  7. }] take:2] subscribeNext:^(id x) { 
  8.     NSLog(@"only 1 and 2 will be print: %@", x); 
  9. }]; 

- takeLast: (NSUInteger)
取最后N次的next值,注意,由于一开始不能知道这个Signal将有多少个next值,所以RAC实现它的方法是将所有next值都存起来,然后原Signal完成时再将后N个依次发送给接收者,但Error发生时依然是立刻发送的。
 
- takeUntil:(RACSignal *)
当给定的signal完成前一直取值。最简单的栗子就是UITextField的rac_textSignal的实现(删减版本):
 
  
  1. - (RACSignal *)rac_textSignal { 
  2.     @weakify(self); 
  3.     return [[[[[RACSignal 
  4.         concat:[self rac_signalForControlEvents:UIControlEventEditingChanged]] 
  5.         map:^(UITextField *x) { 
  6.             return x.text; 
  7.         }] 
  8.         takeUntil:self.rac_willDeallocSignal] // bingo! 
 
也就是这个Signal一直到textField执行dealloc时才停止
 
- takeUntilBlock:(BOOL (^)(id x))
对于每个next值,运行block,当block返回YES时停止取值,如:
 
  
  1. [[self.inputTextField.rac_textSignal takeUntilBlock:^BOOL(NSString *value) { 
  2.     return [value isEqualToString:@"stop"]; 
  3. }] subscribeNext:^(NSString *value) { 
  4.     NSLog(@"current value is not `stop`: %@", value); 
  5. }]; 

- takeWhileBlock:(BOOL (^)(id x))
上面的反向逻辑,对于每个next值,block返回 YES时才取值
 
- skip:(NSUInteger)
从开始跳过N次的next值,简单的例子:
 
  
  1. [[[RACSignal createSignal:^RACDisposable *(id subscriber) { 
  2.     [subscriber sendNext:@"1"]; 
  3.     [subscriber sendNext:@"2"]; 
  4.     [subscriber sendNext:@"3"]; 
  5.     [subscriber sendCompleted]; 
  6.     return nil; 
  7. }] skip:1] subscribeNext:^(id x) { 
  8.     NSLog(@"only 2 and 3 will be print: %@", x); 
  9. }]; 
- skipUntilBlock:(BOOL (^)(id x))
和- takeUntilBlock:同理,一直跳,直到block为YES
 
- skipWhileBlock:(BOOL (^)(id x))
和- takeWhileBlock:同理,一直跳,直到block为NO
 
总结
本节介绍了RAC中Filter类型的Operation,总结一下:
适用场景:需要一个next值集合的子集时
Filter类型:值过滤型和起止点过滤型
值过滤型常用方法: -filter:,-ignore:,-distinctUnitlChanged
起止点过滤型常用方法:take系列和skip系列

你可能感兴趣的:(RAC 知识点整理 - 2 ~ 持续更新)