天天看點

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

轉自:http://www.tuicool.com/articles/e2Q7beN

ReactiveCocoa信号使用方法

時間 2015-08-29 20:58:00   部落格園-原創精華區 原文   http://www.cnblogs.com/purple-sweet-pottoes/p/4769607.html 主題  ReactiveCocoa

最近研究RAC時都是基于UI控件來使用,對單獨的signal沒有使用過,最近在網上看到一篇文章是關于RAC單獨signal的使用。在學習整理後将個人覺得能幫助用于UI控件的一些signal使用方法記錄如下(也許能從中思考出用于UI控件信号組合的方法):

1.基本的signal建立使用

//建立一個signal,并直接發送next事件對象
      RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          NSLog(@"1====");
          //代表信号可以使用next事件,那麼接收的對象為“你确定”
          [subscriber sendNext:@"你确定"];
          //代表此信号可以使用completed事件
          [subscriber sendCompleted];
          //傳回一個空對象
          return nil;
     }];
     //信号的next事件同completed事件
     [signalA subscribeNext:^(id x) {
         NSLog(@"2====%@",x);
     }];
     [signalA subscribeCompleted:^{
         NSLog(@"3====消息送出完成");
     }];
     [signalA subscribeNext:^(id x) {
         NSLog(@"4====我還沒有消失");
     }];
     [signalA subscribeCompleted:^{
         NSLog(@"5====信号還在");
     }];      

接下來是列印結果:讓我們從結果分析其運作過程,首先建立信号,并沒有走block信号設定(3-8行代碼),當其發送next事件時,便會回到block信号設定中查詢此信号有沒有要求發送next事件,如果沒有的話,其next事件便不會被觸發。completed事件同next一樣。那說明單獨建立的signal中你需要設定的是此信号可以執行的事件有哪些! 注意,block信号設定中sendcompleted後寫的事件不會被執行 (讀者可以試着調換block信号設定中的代碼順序檢視結果)

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

2.信号隊列的使用

信号隊列顧名思義就是将一組信号排成隊列,挨個調用,下面我們來看代碼

//建立3個信号來模拟隊列
      RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
          [subscriber sendNext:@"喜歡一個人"];
          [subscriber sendCompleted];
          return nil;
      }];
      RACSignal *signalC = [RACSignal createSignal:^RACDisposable *(id subscriber) {
          [subscriber sendNext:@"直接去表白"];
          [subscriber sendCompleted];
         return nil;
     }];
     RACSignal *signalD = [RACSignal createSignal:^RACDisposable *(id subscriber) {
         [subscriber sendNext:@"成功在一起"];
         [subscriber sendCompleted];
         return nil;
     }];
     //連接配接組隊列:将幾個信号放進一個組裡面,按順序連接配接每個,每個信号必須執行sendCompleted方法後才能執行下一個信号
     RACSignal *signalGroup = [[signalB concat:signalC] concat:signalD];
     [signalGroup subscribeNext:^(id x) {
         NSLog(@"%@",x);
     }];      

以下為列印結果,從執行來看我們隻執行了一個隊列的信号的next事件,但其會将此隊列中所有的signal信号都執行一遍( 注意使用此種隊列必須實作sendcompleted方法 )

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

這裡還有一種組隊列的方式,其可以不要求signal實作sendcompleted方法,具體代碼如下

//信号合并隊列:當其中信号方法執行完後便會執行下個信号
     [[RACSignal merge:@[signalB,signalC,signalD]] subscribeNext:^(id x) {
         // code...
     }];      

3.信号的合并

//此處signal發送了三個next事件,若signalA發送next事件,則觸發三次next事件
      RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
          [subscriber sendNext:@"我想你"];
          [subscriber sendNext:@"我不想你"];
          [subscriber sendNext:@"Test"];
          return nil;
      }];
      RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
          [subscriber sendNext:@"嗯"];
         [subscriber sendNext:@"你豁我"];
         return nil;
     }];
     //合并signalA和signalB
     [[RACSignal combineLatest:@[signalA, signalB]] subscribeNext:^(id x) {
         NSLog(@"%@",x);
     }];      

列印結果如下:從結果可以看出此種合并會将第一個信号中最後一個sendnext與後面信号的所有sendnext結合起來作為一個數組,而next觸發次數以signalB中的next次數為主

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

4.信号的壓縮

RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
          [subscriber sendNext:@"我想你"];
          [subscriber sendNext:@"我不想你"];
          [subscriber sendNext:@"Test"];
          return nil;
      }];
      RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
          [subscriber sendNext:@"嗯"];
          [subscriber sendNext:@"你豁我"];
         return nil;
     }];
     //    壓縮具有一一對應關系,以2個信号中 消息發送數量少的為主對應
     [[signalA zipWith:signalB] subscribeNext:^(RACTuple* x) {
         //解包RACTuple中的對象
         RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
         NSLog(@"%@%@", stringA, stringB);
     }];      

列印結果如下:若将此結果于合并作對比,我們可以發現他們隻是觸發next事件的次數所關聯對象不一樣,是以信号中next事件數量較少的為主

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

5.秩序(同合并組隊列相似)

[[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          NSLog(@"第一步");
          [subscriber sendCompleted];
          return nil;
      }] then:^RACSignal *{
          return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
              NSLog(@"第二步");
              [subscriber sendCompleted];
              return nil;
         }];
     }] then:^RACSignal *{
             return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                 NSLog(@"第三步");
                 return nil;
             }];
     }] subscribeCompleted:^{
17         NSLog(@"完成");
18     }];      

列印結果如下:

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

6.信号定時啟動與逾時處理

//設定定時啟用,類似于NSTimer,這裡需設定take方式
      [[[RACSignal interval: onScheduler:[RACScheduler mainThreadScheduler]] take:]subscribeNext:^(id x) {
              NSLog(@"吃藥");
          }];
      //逾時操作
      [[[RACSignal createSignal:^RACDisposable *(id subscriber) {
          [[[RACSignal createSignal:^RACDisposable *(id subscriber) {
              NSLog(@"我快到了");
              [subscriber sendNext:nil];
             [subscriber sendCompleted];
             return nil;
             //延遲2秒後執行next事件
         }] delay:] subscribeNext:^(id x) {
             NSLog(@"我到了");
             [subscriber sendNext:nil];
             [subscriber sendCompleted];
         }];
         return nil;
     }] timeout: onScheduler:[RACScheduler mainThreadScheduler]] subscribeError:^(NSError *error) {
         NSLog(@"你再不來,我走了");
     }];      

列印結果如下:這裡讀者可以通過調試delay和timeout的數值來測試其使用方式。

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

7.信号設定error後重新執行

__block int i = ;
      [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          
          NSLog(@"i = %d",i);
          if (i == ) {
              [subscriber sendNext:@"i == 2"];
          }else{
              i ++;
              [subscriber sendError:nil];
         }
         return nil;
         //當發送的是error時可以retry重新執行
     }] retry] subscribeNext:^(id x) {
         NSLog(@"%@",x);
     }];      

列印結果如下:若發送的是error則可以使用retry來嘗試重新刺激信号

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

8.信号刺激的條件設定

//建立一個信号
      [[[RACSignal createSignal:^RACDisposable *(id subscriber) {     
           //建立一個定時信号,每隔1秒刺激一次信号 
           [[RACSignal interval: onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {       
              [subscriber sendNext:@"直到世界的盡頭才能把我們分開"];
          }];
          return nil;
          //直到此情況下停止刺激信号
      }] takeUntil:[RACSignal createSignal:^RACDisposable *(id subscriber) {
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)( * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
             NSLog(@"世界的盡頭到了");
             [subscriber sendNext:@"世界的盡頭到了"];
         });
         return nil;
     }]] subscribeNext:^(id x) {
         NSLog(@"%@", x);
     }];      

列印結果如下:這樣當某個條件達到後,就可以停止定時器了

ReactiveCocoa信号使用方法 ReactiveCocoa信号使用方法

以上都屬于我從文章中提取出的個人覺得有幫助的元素,其文章參考位址為: http://www.cocoachina.com/ios/20150817/13071.html 。若上文中有何錯誤使用或了解錯誤的地方望讀者指出。謝謝!