RAC信号处理

map -- 映射

创建一个订阅者的映射并且返回数据(例:将textField的字符串转为其本身长度)

[[self.textField.rac_textSignal map:^id(NSString *value) {
    NSLog(@"%@", value);
    return value.length;
}] subscribeNext:^(id x) {
    NSLog(@"%@", x);
}];

flattenmap -- 扁平映射(信号中的信号)

实际上是根据前一个信号传递进来的参数重新建立了一个信号,这个参数,可能会在创建信号的时候用到,也有可能根本用不到

- (RACSignal *)signInSignal {
    return [RACSignal createSignal:^RACDisposable *(id subscriber){
        [self.signInService
         signInWithUsername:self.usernameTextField.text
         password:self.passwordTextField.text
         complete:^(BOOL success){
             [subscriber sendNext:@(success)];
             [subscriber sendCompleted];
         }];
        return nil;
    }];
}

    [[[self.signInButton
       rac_signalForControlEvents:UIControlEventTouchUpInside]
      map:^id(id x){
          return [self signInSignal];
      }]
     subscribeNext:^(id x){
         NSLog(@"Sign in result: %@", x);
     }];

此时当我们使用map映射的是一个信号(即信号中的信号),映射出来的value是(RACSignal *),这时我们subscribeNext的value即为此信号类型,而不是信号中的value值;所以这里调用flattenMap,创建新的信号,使用(RACSignal *)的value作为新信号的value,也就是我们需要的值。

补充

map 与 swtichToLatest结合类似于flattenMap
switchToLatest:选择最新的信号的value,比如我依次发送3个signal,但是switchToLatest只取第三个响应信号的value。

filter -- 过滤

信号变化时筛选出需要的信号(例:当textField的字符串长度大于3时,信号才会响应)

[[self.textField.rac_textSignal filter:^BOOL(NSString *value) {
    return value.length > 3;
}] subscribeNext:^(id x) {
    NSLog(@"x = %@", x);
}];

take/skip/repeat -- 获取/跳过/重复

RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    [subscriber sendNext:@"1"];
    [subscriber sendNext:@"2"];
    [subscriber sendNext:@"3"];
    [subscriber sendNext:@"4"];
    [subscriber sendNext:@"5"];
    [subscriber sendCompleted];
    return nil;
}] take:2];

[signal subscribeNext:^(id x) {
    NSLog(@"%@", x);
}completed:^{
    NSLog(@"completed");
}];

这个signal只会输出前两个信号1和2还有完成信号completed,skip repeat同理。
相似的还有takeLast takeUntil takeWhileBlock skipWhileBlock skipUntilBlock repeatWhileBlock都可以根据字面意思来理解。

distinctUntilChanged

网络请求中为了减轻服务器压力,无用的请求我们应该尽可能不发送。distinctUntilChanged的作用是使RAC不会连续发送两次相同的信号,这样就解决了这个问题。

[[[self.textField rac_textSignal] distinctUntilChanged] subscribeNext:^(id x) {
    NSLog(@"%@", x);
}];

ignore -- 忽略

指定一个任意类型的量(可以是字符串,数组等),当需要发送信号时讲进行判断,若相同则该信号会被忽略发送。

[[[self.textFild rac_textSignal] ignore:@"good"] subscribeNext:^(id x) {
    NSLog(@"%@", x);
}];

delay -- 延时

    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"delay"];
        [subscriber sendCompleted];
        return nil;
    }] delay:2];
    
    NSLog(@"tag");
    
    [signal subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];

throttle --节流

在我们做搜索框的时候,有时候需求的时实时搜索,即用户每每输入字符,view都要求展现搜索结果。这时如果用户搜索的字符串较长,那么由于网络请求的延时可能造成UI显示错误,并且多次不必要的请求还会加大服务器的压力,这显然是不合理的,此时我们就需要用到节流。

[[[self.textFild rac_textSignal] throttle:0.5] subscribeNext:^(id x) {
    NSLog(@"%@", x);
}];

加了节流管道,后面跟上了类型为NSTimeInterval的参数后,只有0.5S内信号不产生变化才会发送请求,这样快速的输入也不会造成多次输出。

timeout -- 超时信号

当超出限定时间后会给订阅者发送error信号。

RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [[RACScheduler mainThreadScheduler] afterDelay:3 schedule:^{
            [subscriber sendNext:@"delay"];
            [subscriber sendCompleted];
        }];
        return nil;
    }] timeout:2 onScheduler:[RACScheduler mainThreadScheduler]];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"%@", x);
    } error:^(NSError *error) {
        NSLog(@"%@", error);
    }];

由于在创建信号是限定了延迟3秒发送,但是加了timeout2秒的限定,所以这一定是一个超时信号。这个信号被订阅后,由于超时,不会执行订阅成功的输出x方法,而是跳到error的块输出了错误信息。timeout在用RAC封装网络请求时可以节省不少的代码量。

参考自 【cbsfly的博客】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容