公司開發在使用RAC,之前居然一直沒有了解過,獨立開發的弊端,信息閉塞,而且自己也懶,這幾天看了下RAC,確實很強大有木有。
什么是ARC
簡單的說,RAC就是一個第三方庫,他可以大大簡化你的代碼過程。
官方的說,ReactiveCocoa(其簡稱為RAC)是由GitHub開源的一個應用於iOS和OS X開發的新框架。RAC具有函數式編程和響應式編程的特性。
為什么我們要學習RAC?
為了提高我們的開發效率。RAC在某些特定情況下開發時可以大大簡化代碼,並且目前來看安全可靠。
配置RAC環境
我習慣用cocoapods來安裝github上得開源庫,推薦大家使用2.5.0版本以下的RAC
1 platform :ios, ‘8.0’ 2 target “RAC-Text” do 3 4 pod 'ReactiveCocoa', '~> 2.5' 5 6 end
信號signal是RAC的絕對核心,所有的操作都是圍繞着信號來處理的。
比如:創建信號,訂閱信號,發送信號是消息發送的核心步驟。
常見的三個信號類為:
- RACSignal
- RACSubject
- RACReplaySubject
RACSiganl:信號類,一般表示將來有數據傳遞,只要有數據改變,信號內部接收到數據,就會馬上發出數據。
ReactiveCocoa開發中常見用法
1 代替代理.
rac_signalForSelector:用於替代代理。
首先要說的:用RAC寫代理是有局限的,它只能實現返回值為void的代理方法
1 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"RAC" message:@"RAC TEST" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil]; 2 [[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple *tuple) { 3 NSLog(@"%@",tuple.first); 4 NSLog(@"%@",tuple.second); 5 NSLog(@"%@",tuple.third); 6 }]; 7 [alertView show];
我們來看RAC的語句。@selector是指這次事件監聽的方法fromProtocol指依賴的代理。這里block中有一個RACTuple,他相當於是一個集合類,他下面的first,second等就是類的各個參數,我這里點了AlertView第二個按鈕other輸出了一下。
1 2016-01-04 18:24:29.114 RACStudyTest[5003:388870] <UIAlertView: 0x7ff260c90c70; frame = (0 0; 0 0); layer = <CALayer: 0x7ff260c91030>> 2 2016-01-04 18:24:29.115 RACStudyTest[5003:388870] 1 3 2016-01-04 18:24:29.115 RACStudyTest[5003:388870] (null)
可以看出tuple.second是ButtonAtIndex中Button的序號。那么對於上面那個我舉的例子,就可以用switch給各個按鈕添加方法,這樣的代碼看起來更容易理解,方面后期維護。
當然了,AlertView代理也有簡化的代碼。
[[alertView rac_buttonClickedSignal] subscribeNext:^(id x) { NSLog(@"%@",x); }];
這里的x就是各個Button的序號了,可以直接應對我上述遇到的問題。
2代替KVO :
rac_valuesAndChangesForKeyPath:用於監聽某個對象的屬性改變。
RAC中得KVO大部分都是宏定義,所以代碼異常簡潔,簡單來說就是RACObserve(TARGET, KEYPATH)這種形式,TARGET是監聽目標,KEYPATH是要觀察的屬性值,這里舉一個很簡單的例子,如果UIScrollView滾動則輸出success。
1 UIScrollView *scrolView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 200, 400)]; 2 scrolView.contentSize = CGSizeMake(200, 800); 3 scrolView.backgroundColor = [UIColor greenColor]; 4 [self.view addSubview:scrolView]; 5 [RACObserve(scrolView, contentOffset) subscribeNext:^(id x) { 6 NSLog(@"success"); 7 }];
3 監聽事件:
rac_signalForControlEvents:用於監聽某個事件。
1 // 把按鈕點擊事件轉換為信號,點擊按鈕,就會發送信號 2 [[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { 3 NSLog(@"按鈕被點擊了"); 4 }];
給Lable或者View添加監聽
1 UILabel *textLab = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 200, 30)]; 2 textLab.backgroundColor = [UIColor greenColor]; 3 textLab.text = @"********************"; 4 textLab.userInteractionEnabled = YES; 5 [self.view addSubview:textLab]; 6 7 8 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init]; 9 [[tap rac_gestureSignal] subscribeNext:^(id x) { 10 NSLog(@"點擊Lab"); 11 }]; 12 [textLab addGestureRecognizer:tap];
點擊lab控制台會輸出 :點擊Lab
4 代替通知:
rac_addObserverForName:用於監聽某個通知。
在我們的開發中通知也是一個比較常用的功能,主要的應用場景是某個頁面進行數據重傳需要更新model但是點擊返回棧時不會刷新返回界面的數據,這時就可以用通知來更新另一個頁面的數據
首先,在某個頁面中我們需要發出通知,這里就是最基本的通知的寫法。發送名為postdata的通知並傳送一個數組dataArray
1 NSMutableArray *dataArray = [[NSMutableArray alloc] initWithObjects:@"1", @"2", @"3", nil]; 2 [[NSNotificationCenter defaultCenter] postNotificationName:@"postData" object:dataArray];
而在接受的頁面我們需要增加觀察者並接受數組,這時我們的RAC就派上用場了。
1 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"postData" object:nil] subscribeNext:^(NSNotification *notification) { 2 NSLog(@"%@", notification.name); 3 NSLog(@"%@", notification.object); 4 }];
當這個頁面監聽到名為postdata的通知時他就會執行block中的方法,當然這里的參數改成id x也是可以的,這里用NSNotification主要是強調它的類型。讓我們看看控制台的輸出
1 2016-01-04 20:10:52.274 RACStudyTest[5918:439077] postData 2 2016-01-04 20:10:52.275 RACStudyTest[5918:439077] ( 3 1, 4 2, 5 3 6 )
可見,notification.object就是我們想要的數組,當然我們也可以傳一些model。值得一提的是,RAC中的通知不需要remove observer,因為在rac_add方法中他已經寫了remove。
5 監聽文本框文字改變:
rac_textSignal:只要文本框發出改變就會發出這個信號。
1 UITextField *text1 = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 30)]; 2 text1.backgroundColor = [UIColor cyanColor]; 3 [self.view addSubview:text1]; 4 5 [[text1 rac_textSignal] subscribeNext:^(id x) { 6 static int i = 0; 7 i++; 8 // text改變就會打印 9 NSLog(@"厲害了我的哥------ %d", i); 10 }];
6 處理當界面有多次請求時,需要都獲取到數據時,才能展示界面
rac_liftSelector:withSignalsFromArray:Signals:當傳入的Signals(信號數組),每一個signal都至少sendNext過一次,就會去觸發第一個selector參數的方法。
使用注意:幾個信號,參數一的方法就幾個參數,每個參數對應信號發出的數據。
1 // 處理多個請求,都返回結果的時候,統一做處理. 2 RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { 3 // 發送請求1 4 [subscriber sendNext:@"發送請求1"]; 5 return nil; 6 }]; 7 8 RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { 9 // 發送請求2 10 [subscriber sendNext:@"發送請求2"]; 11 return nil; 12 }]; 13 14 // 使用注意:幾個信號,參數一的方法就幾個參數,每個參數對應信號發出的數據。 15 [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]]; 16 } 17 // 更新UI(該方法有要求,有多少個信號就要求有多少個參數,參數的內容就是發送的數據。) 18 - (void)updateUIWithR1:(id)data r2:(id)data1 19 { 20 NSLog(@"更新UI%@,%@",data,data1); 21 }
內容來自網絡摘抄和總結
http://www.jianshu.com/p/769025368bcb
http://www.cnblogs.com/qiyer/p/5483162.html
http://www.jianshu.com/p/ff79a5ae0353
