美文网首页ReactiveCocoa
RAC一些常见方法的个人理解

RAC一些常见方法的个人理解

作者: 水水兔 | 来源:发表于2019-10-30 11:54 被阅读0次

RACSubject

冷热信号概念

信号源分为热信号和冷信号两种,热信号是不管有没有订阅者都会发消息,而冷信号只有在订阅都订阅时才会发送消息。通俗来讲,热信号就像直播,不管有没有观众都会一直播,当观众看时,也只能看这个时间之后的内容,这个点之前的看不到,而冷信息就相当于点播,每次有订阅者时,视频内容都会从头到尾的播一遍 参考

举栗子:

  RACSubject *subject = [RACSubject subject];

    // Subscriber 1
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"1st Sub: %@", x);
    }];
    [subject sendNext:@1];

    // Subscriber 2
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"2nd Sub: %@", x);
    }];
    [subject sendNext:@2];

    // Subscriber 3
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"3rd Sub: %@", x);
    }];
    [subject sendNext:@3];
    [subject sendCompleted];

结果:

2019-10-30 10:15:09.190910+0800 RACTest[22045:1676452] 1st Sub: 1
2019-10-30 10:15:09.191331+0800 RACTest[22045:1676452] 1st Sub: 2
2019-10-30 10:15:09.191606+0800 RACTest[22045:1676452] 2nd Sub: 2
2019-10-30 10:15:09.191764+0800 RACTest[22045:1676452] 1st Sub: 3
2019-10-30 10:15:09.191970+0800 RACTest[22045:1676452] 2nd Sub: 3
2019-10-30 10:15:09.192099+0800 RACTest[22045:1676452] 3rd Sub: 3

RACSignal bind的理解

bind方法的实现:

 - (RACSignal *)bind:(RACStreamBindBlock (^)(void))block {  
    return [RACSignal createSignal:^RACDisposable *(id subscriber) {  //(1)
        RACStreamBindBlock bindBlock = block();                       //(2)
        [self subscribeNext:^(id x) {                                 //(3)
            BOOL stop = NO;
            RACSignal *signal = (RACSignal *)bindBlock(x, &stop);     //(4)
            if (signal !=nil) {
                [signal subscribeNext:^(id x) {                       //(5)
                    [subscriber sendNext:x];                          //(6)
                } error:^(NSError *error) {
                    [subscriber sendError:error];                     //(10)
                } completed:^{
                    [subscriber sendCompleted];                       //(9)
                }];
            }
            if (signal == nil || stop) {
                [subscriber sendCompleted];                           //(9)
            }
        } error:^(NSError *error) {
            [subscriber sendError:error];                             //(10)
        } completed:^{
            [subscriber sendCompleted];                               //(9)
        }];        
        return nil;
    }];
}
  • 假设原信号为A,bind方法是创建一个新的信号B
  • B信号调用subscribeNext时,会执行block(1),block(1)执行时,会去订阅信号A,在信号A发出变化时,调用block(3),block(3)会根据bind返回的block生成一个新的信号C,并且订阅信号C,信号C收到变化消息时,会通知B的订阅都,此时就触发了B的订阅回调。
RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"发送信号signalA");
        [subscriber sendNext:@"我是signalA"];
        [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{
            NSLog(@"清理信号signalA");
        }];
    }];
    
    RACSignal *signalB = [signalA bind:^RACSignalBindBlock _Nonnull{
        return ^(id value, BOOL *stop){
           NSString *newString = [NSString stringWithFormat:@"%@经过变更",value];
            NSLog(@"内容更改%@",newString);
           return [RACSignal return:newString];
        };
    }];
    NSLog(@"订阅信号signalB");

    [signalB subscribeNext:^(id  _Nullable x) {
        NSLog(@"信号signalB收到通知:%@",x);

    }];

打印结果:

2019-10-30 10:03:35.450362+0800 RACTest[21997:1672464] 订阅信号signalB
2019-10-30 10:03:35.453114+0800 RACTest[21997:1672464] 发送信号signalA
2019-10-30 10:03:35.453235+0800 RACTest[21997:1672464] 内容更改我是signalA经过变更
2019-10-30 10:03:35.453652+0800 RACTest[21997:1672464] 信号signalB收到通知:我是signalA经过变更
2019-10-30 10:03:35.454191+0800 RACTest[21997:1672464] 清理信号signalA

zip合并信号

我说下个人猜的实现方式,如果有不对的地方,还请看官指正,以免误人子弟。
zip会给每个信号分配一个类似队列的存储空间(FIFO),信号调sendNext时,就往其队列里存储这个值,每次存储前,都会检查下,是不是zip的几个信号都有值了,如果是则回调,会删除输出过的值,否则不回调,当有一个信号发送sendCompleted时,等此信号队列的值都输出完后,zip执行complete。

请吃栗子:

 RACSubject *A = [RACSubject subject];
    RACSubject *B = [RACSubject subject];
    RACSubject *C = [RACSubject subject];

    RACSignal *zip = [RACSignal zip:@[A,B,C] reduce:^id(NSString *a,NSString *b,NSString *c){
        return [NSString stringWithFormat:@"%@%@%@",a,b,c];
    }];
    [zip subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];

    [A sendNext:@"A1"];
    [A sendNext:@"A2"];
    [B sendNext:@"B1"];
    [C sendNext:@"C1"];
    [C sendNext:@"C2"];
    [A sendNext:@"A3"];
    [B sendNext:@"B2"];
    [B sendNext:@"B3"];
    [C sendNext:@"C3"];

结果:

2019-10-30 10:17:22.584257+0800 RACTest[22056:1677335] A1B1C1
2019-10-30 10:17:22.584706+0800 RACTest[22056:1677335] A2B2C2
2019-10-30 10:17:22.585092+0800 RACTest[22056:1677335] A3B3C3

combineLatestWith合并信号

理解:
1、存储每个信号的value,等所有合并的信号都发送过sendNext时,才输出
2、如果在输出前,某个信号调sendNext两次以上,则会用最新的值覆盖旧值。
3、输出后,信号的值不会被清除

请吃票子:

  RACSubject *A = [RACSubject subject];
    RACSubject *B = [RACSubject subject];
    RACSubject *C = [RACSubject subject];

    RACSignal *combined = [RACSignal combineLatest:@[A,B,C] reduce:^id(NSString *a,NSString *b,NSString *c){
      return [NSString stringWithFormat:@"%@%@%@",a,b,c];
    }];
    [combined subscribeNext:^(id x) {
      NSLog(@"%@", x);
    }];

    [A sendNext:@"A1"];
    [A sendNext:@"A2"];
    [B sendNext:@"B1"];
    [C sendNext:@"C1"];
    [C sendNext:@"C2"];
    [A sendNext:@"A3"];
    [A sendNext:@"A4"];
    [B sendNext:@"B2"];

结果:

2019-10-30 10:36:05.440970+0800 RACTest[22127:1682750] A2B1C1
2019-10-30 10:36:05.441308+0800 RACTest[22127:1682750] A2B1C2
2019-10-30 10:36:05.441660+0800 RACTest[22127:1682750] A3B1C2
2019-10-30 10:36:05.442017+0800 RACTest[22127:1682750] A4B1C2
2019-10-30 10:36:05.442218+0800 RACTest[22127:1682750] A4B2C2

concat

理解:
1、串行执行
2、只有等上一个信号执行sendCompleted时才会响应下一个信号的sendNext(只是不响应,但不会阻塞线程往下走哦)

请吃票子:

  RACSubject *A = [RACSubject subject];
    RACSubject *B = [RACSubject subject];
    RACSubject *C = [RACSubject subject];

    RACSignal *concat = [[A concat:B]concat:C];
    [concat subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];

    [A sendNext:@"A1"];
    [A sendNext:@"A2"];
    [A sendCompleted];
    [B sendNext:@"B1"];
    [C sendNext:@"C1"];
    [C sendNext:@"C2"];
    [A sendNext:@"A3"];
    [A sendNext:@"A4"];
    [B sendNext:@"B2"];

结果:

2019-10-30 10:41:35.082761+0800 RACTest[22150:1684987] A1
2019-10-30 10:41:35.082870+0800 RACTest[22150:1684987] A2
2019-10-30 10:41:35.083049+0800 RACTest[22150:1684987] B1
2019-10-30 10:41:35.083093+0800 RACTest[22150:1684987] B2

merge

1、只要有信号调sendNext都会响应。
2、某个信号 发送sendCompleted只停止当前的信号。
3、所有的信号sendCompleted时,merge才complete。

请吃栗子

RACSubject *A = [RACSubject subject];
    RACSubject *B = [RACSubject subject];
    RACSubject *C = [RACSubject subject];

    RACSignal *merge = [RACSignal merge:@[A,B,C]];
    [merge subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@", x);

    } completed:^{
        NSLog(@"merge完成");
    }];

    [A sendNext:@"A1"];
    [A sendNext:@"A2"];
    [A sendCompleted];
    [B sendNext:@"B1"];
    [C sendNext:@"C1"];
    [C sendNext:@"C2"];
    [A sendNext:@"A3"];
    [B sendNext:@"B2"];
    [B sendNext:@"B3"];
    [B sendCompleted];
    [C sendCompleted];

结果

2019-10-30 11:49:22.343006+0800 RACTest[22417:1706356] A1
2019-10-30 11:49:22.343117+0800 RACTest[22417:1706356] A2
2019-10-30 11:49:22.343243+0800 RACTest[22417:1706356] B1
2019-10-30 11:49:22.343291+0800 RACTest[22417:1706356] C1
2019-10-30 11:49:22.343324+0800 RACTest[22417:1706356] C2
2019-10-30 11:49:22.343357+0800 RACTest[22417:1706356] B2
2019-10-30 11:49:22.343562+0800 RACTest[22417:1706356] B3
2019-10-30 11:49:22.343676+0800 RACTest[22417:1706356] merge完成

相关文章

  • RAC一些常见方法的个人理解

    RACSubject 冷热信号概念 信号源分为热信号和冷信号两种,热信号是不管有没有订阅者都会发消息,而冷信号只有...

  • iOS开发之RAC(二)进阶篇

    初级篇简单的介绍了RAC。本文将介绍RAC在项目中常见的类和最常用的一些操作方法!!! 一、常见类 1、RACSi...

  • RAC常见用法(三)

    本文将要介绍的RAC的常见用法大纲: RAC的映射: 首先看flattenMap:这个方法, 其实这个方法的内部是...

  • RAC一些常见用法(五)

    本demo详见github 1.常见的用法 2.RAC常见的宏 3.发送验证码 友情链接: RAC(一) RAC(...

  • 记录ReactiveObjC的一些用法

    常见用法 rac_signalForSelector : 代替代理 rac_valuesAndChangesFor...

  • RAC(ReactiveCocoa)使用方法(一)

    RAC(ReactiveCocoa)使用方法(一)RAC(ReactiveCocoa)使用方法(二) 什么是RAC...

  • iOS开发 「RAC」RAC常见宏方法的妙用

    一、 RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定 二、 ...

  • RAC常见宏以及rac_lift方法

    使用场景:当有多个任务执行时,全部执行完毕才能执行其他操作,注意方法的参数必须跟后面信号一一对应不然就会报错,方法...

  • RAC(二)

    本demo详见github 下面我们来看看RAC的常见的类的使用 1.RAC常见类-RACSiganl RACSi...

  • RAC常见用法(二)

    接着说RAC的常见用法 : 这是今天要说的几个常见用法: rac_liftSelector 当多个信号都被发送时,...

网友评论

    本文标题:RAC一些常见方法的个人理解

    本文链接:https://www.haomeiwen.com/subject/emanvctx.html