轉自: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信号設定中的代碼順序檢視結果)
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方法 )
這裡還有一種組隊列的方式,其可以不要求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次數為主
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事件數量較少的為主
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 }];
列印結果如下:
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的數值來測試其使用方式。
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來嘗試重新刺激信号
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);
}];
列印結果如下:這樣當某個條件達到後,就可以停止定時器了
以上都屬于我從文章中提取出的個人覺得有幫助的元素,其文章參考位址為: http://www.cocoachina.com/ios/20150817/13071.html 。若上文中有何錯誤使用或了解錯誤的地方望讀者指出。謝謝!