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