zoukankan      html  css  js  c++  java
  • ReactiveCocoa信号使用方法

      最近研究RAC时都是基于UI控件来使用,对单独的signal没有使用过,最近在网上看到一篇文章是关于RAC单独signal的使用。在学习整理后将个人觉得能帮助用于UI控件的一些signal使用方法记录如下(也许能从中思考出用于UI控件信号组合的方法):

      1.基本的signal创建使用

     1 //创建一个signal,并直接发送next事件对象
     2     RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     3         NSLog(@"1====");
     4         //代表信号可以使用next事件,那么接收的对象为“你确定”
     5         [subscriber sendNext:@"你确定"];
     6         //代表此信号可以使用completed事件
     7         [subscriber sendCompleted];
     8         //返回一个空对象
     9         return nil;
    10     }];
    11     //信号的next事件同completed事件
    12     [signalA subscribeNext:^(id x) {
    13         NSLog(@"2====%@",x);
    14     }];
    15     [signalA subscribeCompleted:^{
    16         NSLog(@"3====消息提交完成");
    17     }];
    18     [signalA subscribeNext:^(id x) {
    19         NSLog(@"4====我还没有消失");
    20     }];
    21     [signalA subscribeCompleted:^{
    22         NSLog(@"5====信号还在");
    23     }];

    接下来是打印结果:让我们从结果分析其运行过程,首先创建信号,并没有走block信号设置(3-8行代码),当其发送next事件时,便会回到block信号设置中查询此信号有没有要求发送next事件,如果没有的话,其next事件便不会被触发。completed事件同next一样。那说明单独创建的signal中你需要设置的是此信号可以执行的事件有哪些!注意,block信号设置中sendcompleted后写的事件不会被执行(读者可以试着调换block信号设置中的代码顺序查看结果)

      2.信号队列的使用

      信号队列顾名思义就是将一组信号排成队列,挨个调用,下面我们来看代码

     1     //创建3个信号来模拟队列
     2     RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
     3         [subscriber sendNext:@"喜欢一个人"];
     4         [subscriber sendCompleted];
     5         return nil;
     6     }];
     7     RACSignal *signalC = [RACSignal createSignal:^RACDisposable *(id subscriber) {
     8         [subscriber sendNext:@"直接去表白"];
     9         [subscriber sendCompleted];
    10         return nil;
    11     }];
    12     RACSignal *signalD = [RACSignal createSignal:^RACDisposable *(id subscriber) {
    13         [subscriber sendNext:@"成功在一起"];
    14         [subscriber sendCompleted];
    15         return nil;
    16     }];
    17     //连接组队列:将几个信号放进一个组里面,按顺序连接每个,每个信号必须执行sendCompleted方法后才能执行下一个信号
    18     RACSignal *signalGroup = [[signalB concat:signalC] concat:signalD];
    19     [signalGroup subscribeNext:^(id x) {
    20         NSLog(@"%@",x);
    21     }];

    以下为打印结果,从执行来看我们只执行了一个队列的信号的next事件,但其会将此队列中所有的signal信号都执行一遍(注意使用此种队列必须实现sendcompleted方法)

    这里还有一种组队列的方式,其可以不要求signal实现sendcompleted方法,具体代码如下

    1 //信号合并队列:当其中信号方法执行完后便会执行下个信号
    2     [[RACSignal merge:@[signalB,signalC,signalD]] subscribeNext:^(id x) {
    3         // code...
    4     }];

      3.信号的合并

     1     //此处signal发送了三个next事件,若signalA发送next事件,则触发三次next事件
     2     RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
     3         [subscriber sendNext:@"我想你"];
     4         [subscriber sendNext:@"我不想你"];
     5         [subscriber sendNext:@"Test"];
     6         return nil;
     7     }];
     8     RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
     9         [subscriber sendNext:@""];
    10         [subscriber sendNext:@"你豁我"];
    11         return nil;
    12     }];
    13     //合并signalA和signalB
    14     [[RACSignal combineLatest:@[signalA, signalB]] subscribeNext:^(id x) {
    15         NSLog(@"%@",x);
    16     }];

    打印结果如下:从结果可以看出此种合并会将第一个信号中最后一个sendnext与后面信号的所有sendnext结合起来作为一个数组,而next触发次数以signalB中的next次数为主

      4.信号的压缩

     1     RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
     2         [subscriber sendNext:@"我想你"];
     3         [subscriber sendNext:@"我不想你"];
     4         [subscriber sendNext:@"Test"];
     5         return nil;
     6     }];
     7     RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
     8         [subscriber sendNext:@""];
     9         [subscriber sendNext:@"你豁我"];
    10         return nil;
    11     }];
    12     //    压缩具有一一对应关系,以2个信号中 消息发送数量少的为主对应
    13     [[signalA zipWith:signalB] subscribeNext:^(RACTuple* x) {
    14         //解包RACTuple中的对象
    15         RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
    16         NSLog(@"%@%@", stringA, stringB);
    17     }];

    打印结果如下:若将此结果于合并作对比,我们可以发现他们只是触发next事件的次数所关联对象不一样,是以信号中next事件数量较少的为主

      5.秩序(同合并组队列相似)

     1     [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     2         NSLog(@"第一步");
     3         [subscriber sendCompleted];
     4         return nil;
     5     }] then:^RACSignal *{
     6         return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     7             NSLog(@"第二步");
     8             [subscriber sendCompleted];
     9             return nil;
    10         }];
    11     }] then:^RACSignal *{
    12             return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    13                 NSLog(@"第三步");
    14                 return nil;
    15             }];
    16     }] subscribeCompleted:^{
    17         NSLog(@"完成");
    18     }];

    打印结果如下:

      6.信号定时启动与超时处理

     1 //设置定时启用,类似于NSTimer,这里需设置take方式
     2     [[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] take:5]subscribeNext:^(id x) {
     3             NSLog(@"吃药");
     4         }];
     5     //超时操作
     6     [[[RACSignal createSignal:^RACDisposable *(id subscriber) {
     7         [[[RACSignal createSignal:^RACDisposable *(id subscriber) {
     8             NSLog(@"我快到了");
     9             [subscriber sendNext:nil];
    10             [subscriber sendCompleted];
    11             return nil;
    12             //延迟2秒后执行next事件
    13         }] delay:2] subscribeNext:^(id x) {
    14             NSLog(@"我到了");
    15             [subscriber sendNext:nil];
    16             [subscriber sendCompleted];
    17         }];
    18         return nil;
    19     }] timeout:1 onScheduler:[RACScheduler mainThreadScheduler]] subscribeError:^(NSError *error) {
    20         NSLog(@"你再不来,我走了");
    21     }];

    打印结果如下:这里读者可以通过调试delay和timeout的数值来测试其使用方式。

      7.信号设置error后重新执行

     1 __block int i = 0;
     2     [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     3         
     4         NSLog(@"i = %d",i);
     5         if (i == 5) {
     6             [subscriber sendNext:@"i == 2"];
     7         }else{
     8             i ++;
     9             [subscriber sendError:nil];
    10         }
    11         return nil;
    12         //当发送的是error时可以retry重新执行
    13     }] retry] subscribeNext:^(id x) {
    14         NSLog(@"%@",x);
    15     }];

    打印结果如下:若发送的是error则可以使用retry来尝试重新刺激信号

      8.信号刺激的条件设置

     1     //创建一个信号
     2     [[[RACSignal createSignal:^RACDisposable *(id subscriber) {     
     3          //创建一个定时信号,每隔1秒刺激一次信号 
     4          [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {       
     5             [subscriber sendNext:@"直到世界的尽头才能把我们分开"];
     6         }];
     7         return nil;
     8         //直到此情况下停止刺激信号
     9     }] takeUntil:[RACSignal createSignal:^RACDisposable *(id subscriber) {
    10         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    11             NSLog(@"世界的尽头到了");
    12             [subscriber sendNext:@"世界的尽头到了"];
    13         });
    14         return nil;
    15     }]] subscribeNext:^(id x) {
    16         NSLog(@"%@", x);
    17     }];

    打印结果如下:这样当某个条件达到后,就可以停止定时器了

    以上都属于我从文章中提取出的个人觉得有帮助的元素,其文章参考地址为:http://www.cocoachina.com/ios/20150817/13071.html。若上文中有何错误使用或理解错误的地方望读者指出。谢谢!

  • 相关阅读:
    MVC-- 网页中整、小数加法
    装饰器练习——Python
    父类对象对子类对象方法的调用
    Python----父与子的关系
    分析句子,以空格为分割找出单词
    模拟成绩数据库
    【算法竞赛-入门经典】圆柱体的表面积
    【算法竞赛-入门经典】计算并输出1+2的值
    前中后缀表达式
    代码基本结构
  • 原文地址:https://www.cnblogs.com/purple-sweet-pottoes/p/4769607.html
Copyright © 2011-2022 走看看