RACSignal 浅析

RACSignalRAC 中的核心并不过分,这个框架的本质就是信号的产生,分发与订阅。


“A signal, represented by the RACSignal class, is a push-driven
stream.”

官方文档介绍中有说 signalpush-driven 的,但信号在没有订阅者的时候是 cold 状态,只有被订阅后才变成 hot 并开始分发。也就是常说的冷信号与热信号。
大神 sunnyxx 把这种现象生动的比喻成巧克力工厂,生产一个吃一个。有订单才生产,没有订单就不开工。

// 创建一个基本 signal
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendNext:@2];
        [subscriber sendCompleted];
        return nil;
    }];

这样没人订阅什么也不会发生,block 里面的代码并没有执行。

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

有人订阅(有了订单)后信号被激活,发一个就收到一个(生产一个吃一个巧克力)。

2017-04-18 11:46:04.717 simpleRacDemo[15054:2153646] 1
2017-04-18 11:46:04.717 simpleRacDemo[15054:2153646] 2
2017-04-18 11:46:04.717 simpleRacDemo[15054:2153646] dispose

一共生产了两块巧克力。


最基本的 next、completed,error

[signal subscribeNext:^(id x) {// 信号产生的值
    NSLog(@"x = %@", x);
} error:^(NSError *error) {// 错误返回
    NSLog(@"error = %@", error);
} completed:^{// 信号成功结束,不带值
    NSLog(@"completed");
}];

当信号成功结束后会 dispose 表明自己已经被了结。


map 映射

map 这个概念在很多语言都有,在 RAC 中会把 signal 发送来的值逐个过滤一次,输出新的目标序列。

    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendNext:@2];
        [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{
            NSLog(@"dispose");
        }];
    }];
    
    [[signal map:^id _Nullable(id  _Nullable value) {
        return [value isEqual:@1] ? @1 : @"not equal";
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
2017-04-18 15:05:27.185 simpleRacDemo[15463:2436314] 1
2017-04-18 15:05:27.186 simpleRacDemo[15463:2436314] not equal
2017-04-18 15:05:27.186 simpleRacDemo[15463:2436314] dispose

当收到 @2 时经过我们三目运算的处理打印了 not equal


filter 过滤

这个看名字就会了解是过滤掉不符合条件的返回值
稍微改一下上面的订阅

    [[signal filter:^BOOL(id  _Nullable value) {
        return [value isEqual:@1];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
2017-04-18 15:10:57.899 simpleRacDemo[15515:2461820] 1
2017-04-18 15:10:57.900 simpleRacDemo[15515:2461820] dispose

只有 1 满足条件


以上是十分常用的方法,RAC 中的其它方法还有很多。可以根据相应的业务场景深入研究。

take — takeLast/takeUntil/takeWhileBlock

最基本的使用就是拿,后面参数是 NSInteger ,代表了拿前这么多个值。

skip — skipWhileBlock/skipUntilBlock

相对应的跳过前 n 个值。

repeat/repeatWhileBlock

重复发送信号

delay

延迟发送


throttle 节流

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

文本输入变化很多,限制0.5秒无变化才响应。


distinctUntilChanged

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

相应的不发送两次相同的请求,有变化才响应。


timeout 超时


ignore

还是把上面的订阅修改一下,忽视 @1。

    [[signal ignore:@1] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
2017-04-18 15:44:51.597 simpleRacDemo[15975:2565685] 2
2017-04-18 15:44:51.597 simpleRacDemo[15975:2565685] dispose

如同期望只剩下了 @2。


小结

  • RACSignal 是有副作用的,在上一篇文章中有过简单理解。ReactiveCocoa 冷热信号 -
  • RAC 的英文名名已经十分的精准,翻译成中文反而影响理解,尽量看方法名和注释理解意图。
  • RAC 持续学习更新中,作为个人的笔记同时也分享给大家,有错误的地方,欢迎大家批评指正,共同探讨。

参考资料:

  • Reactive Cocoa Tutorial 3 = RACSignal的巧克力工厂 · sunnyxx的技术博客
  • 探究RAC-RAC信号处理方法归纳 – cbs->fffffly

你可能感兴趣的:(RACSignal 浅析)