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。若上文中有何錯誤使用或理解錯誤的地方望讀者指出。謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM