ReactiveCocoa入门第二篇过滤器学习笔记

作者: shaneZhang 分类: ios技术 发布时间: 2016-01-13 15:01

信号的过滤

一个Signal源可以产生一系列next值,但并非所有值都是需要的,具体的Subscriber可以选择在原有Signal上套用Filter操作来过滤掉不需要的值。

经过总结,这些filter大概可以分成两类:next值过滤类型和起止点过滤类型

值过滤类型Filters

– filter: (BOOL (^)(id value))


[[self.inputTextField.rac_textSignal filter:^BOOL(NSString *value) {
    return [value hasPrefix:@"sunny"];
}] subscribeNext:^(NSString *value) {
    NSLog(@"This value has prefix `sunny` : %@", value);
}];

– ignore: (id)

忽略给定的值,注意,这里忽略的既可以是地址相同的对象,也可以是- isEqual:结果相同的值,也就是说自己写的Model对象可以通过重写- isEqual:方法来使- ignore:生效。


[[self.inputTextField.rac_textSignal ignore:@"sunny"] subscribeNext:^(NSString *value) {
    NSLog(@"`sunny` could never appear : %@", value);
}];

– ignoreValues

这个比较极端,忽略所有值,只关心Signal结束,也就是只取Comletion和Error两个消息,中间所有值都丢弃。
注意,这个操作应该出现在Signal有终止条件的的情况下,如rac_textSignal这样除dealloc外没有终止条件的Signal上就不太可能用到。

– distinctUntilChanged

也是一个相当常用的Filter(但它不是- filter:的衍生方法),它将这一次的值与上一次做比较,当相同时(也包括- isEqual:)被忽略掉。
比如UI上一个Label绑定了一个值,根据值更新显示的内容:


RAC(self.label, text) = [RACObserve(self.user, username) distinctUntilChanged];
self.user.username = @"sunnyxx"; // 1st
self.user.username = @"sunnyxx"; // 2nd
self.user.username = @"sunnyxx"; // 3rd

起止点过滤类型

除了被动的当next值来的时候做判断,也可以主动的提前选择开始和结束条件,分为两种类型:
take型(取)和skip型(跳)

– take: (NSUInteger)

从开始一共取N次的next值,不包括Competion和Error,如:


[[[RACSignal createSignal:^RACDisposable *(id subscriber) {
    [subscriber sendNext:@"1"];
    [subscriber sendNext:@"2"];
    [subscriber sendNext:@"3"];
    [subscriber sendCompleted];
    return nil;
}] take:2] subscribeNext:^(id x) {
    NSLog(@"only 1 and 2 will be print: %@", x);
}];

– takeLast: (NSUInteger)

取最后N次的next值,注意,由于一开始不能知道这个Signal将有多少个next值,所以RAC实现它的方法是将所有next值都存起来,然后原Signal完成时再将后N个依次发送给接收者,但Error发生时依然是立刻发送的。

– takeUntil:(RACSignal *)

当给定的signal完成前一直取值。最简单的栗子就是UITextField的rac_textSignal的实现(删减版本):


- (RACSignal *)rac_textSignal {
    @weakify(self);
    return [[[[[RACSignal
        concat:[self rac_signalForControlEvents:UIControlEventEditingChanged]]
        map:^(UITextField *x) {
            return x.text;
        }]
        takeUntil:self.rac_willDeallocSignal] // bingo!
}

更多更详细的用法参见官方文档
本文仅记录了部分常用的代码片段,具体可以参见原文博客

如果觉得我的文章对您有用,请随意打赏。如果有其他问题请联系博主QQ(909491009)或者下方留言!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注