ReactiveCocoa使用個人總結(jié)
ReactiveCocoa簡介
ReactiveCocoa(簡稱RAC)是由Github開源的一個應(yīng)用于iOS和OS開發(fā)的新框架砌滞。
ReactiveCocoa的作用
在我們iOS開發(fā)過程中,當(dāng)某些事件響應(yīng)的時候贝润,需要處理某些業(yè)務(wù)邏輯,這些事件都會用不同的方式來處理按傅。比如:按鈕的點擊使用action胧卤、UIScrollView的滾動使用的delegate、監(jiān)測屬性的值改變使用KVO等系統(tǒng)提供的方式枝誊。
RAC就是把這些不同的響應(yīng)事件的方式統(tǒng)一起來,使這些方式都可以通過RAC來處理绝骚。
RAC為事件提供了很多的處理方法祠够,而且利用RAC來處理事件很方便,可以把要處理的事情和監(jiān)聽的代碼放一起止剖,方便我們的管理落君,這樣就不需要跳轉(zhuǎn)到對應(yīng)的方法里去處理,非常符合我們開發(fā)中高內(nèi)聚绎速,低耦合的思想。
RAC在某些特定情況下開發(fā)時可以大大簡化代碼洒宝,提高開發(fā)效率,并且是安全可靠的雁歌。
配置RAC環(huán)境
使用cocoapods來獲取github上的開源庫:
pod 'ReactiveCocoa'
如何使用RAC
- RACSignal
信號類,一般表示將來會有數(shù)據(jù)傳遞,只要數(shù)據(jù)改變橡庞,信號內(nèi)部接收到數(shù)據(jù)扒最,就會馬上發(fā)出數(shù)據(jù)。
- RACSignal只是表示當(dāng)數(shù)據(jù)改變時吧趣,信號內(nèi)部會發(fā)出數(shù)據(jù),他本身不具備發(fā)送信號的能力岔霸,而是交給內(nèi)部的一個訂閱者
subscriber
發(fā)出俯渤。
- 默認一個信號都是冷信號,也就是說值改變了也不會觸發(fā)八匠,只有訂閱了這個信號,值改變了才會觸發(fā)坑夯。
- 訂閱信號:調(diào)用RACSignal的
subscribeNext:
方法就可以訂閱信號抡四。
// 創(chuàng)建一個RACSignal信號
RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 每當(dāng)有訂閱者訂閱信號 就會調(diào)用這個block
// 發(fā)送信號
[subscriber sendNext:@"Hello"];
// 如果不再發(fā)送數(shù)據(jù),最好調(diào)用此方法發(fā)送信號完成
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// 當(dāng)信號發(fā)送完成或者發(fā)送錯誤跨释,就會自動執(zhí)行這個block厌处,取消訂閱信號
NSLog(@"信號被銷毀");
}];
}];
// 訂閱信號,才會激活信號
[signal subscribeNext:^(id x){
// 每當(dāng)有信號發(fā)出數(shù)據(jù) 就會調(diào)用block
NSLog(@"接收到數(shù)據(jù)%@",x);
}]
- target-action
RAC最基本的使用就是對事件的監(jiān)聽缆娃。我們來看以下代碼:
RACSignal * textFieldSignal = [textField rac_signalForControlEvents:UIControlEventEditingChanged];
[textFieldSignal subscribeNext:^(id x) {
NSLog(@"變化的text:%@",x);
}];
這段代碼實現(xiàn)了監(jiān)聽UITextField
的UIControlEventEditingChanged
事件,當(dāng)textField
里的內(nèi)容發(fā)生變化時贯要,發(fā)送變化的數(shù)據(jù)調(diào)用block種的內(nèi)容將變化的內(nèi)容實時打印出來。這兩段代碼通常會連在一起寫:
[[textField rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(id x) {
NSLog(@"變化的text:%@",x);
}];
同樣的字逗,我們以這段代碼為模板進行RAC的使用宅广,UIButton
的點擊事件我們也可以用RAC進行監(jiān)測,添加方法俭厚,對于UITextField
的文字更改的監(jiān)聽也有更簡單的寫法:
// UIButton添加RAC監(jiān)聽點擊方法
[[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
NSLog(@"點擊button:%@",x);
}];
// 對于UITextField 文字更改的監(jiān)聽
[textField.rac_textSignal subscribeNext:^(id x) {
NSLog(@"變化的text:%@",x);
}]
RAC的一些常見操作方法
-
ReactiveCocoa操作方法之映射(flattenMap驶臊,Map)
-
flattenMap
,Map
用于把源信號內(nèi)容映射成新的內(nèi)容。
flattenMap的使用:把源信號的內(nèi)容映射成一個新的信號关翎,信號可以是任意類型
flattenMap
中的block返回的是信號 -
```
// 創(chuàng)建信號中的信號
RACSubject * signalOfSignals = [RACSubject subject];
RACSubject * signals = [RACSubject subject];
[[signalOfSignals flattenMap:^RACStream *(id value) {
// 當(dāng)signalOfsignals 發(fā)出signals 信號才會調(diào)用 這里的value返回的是信號
return value;
}] subscribeNext:^(id x) {
// 只有signalOfSignals發(fā)出的signals也發(fā)出了內(nèi)容(也就是最后一行代碼執(zhí)行)才會調(diào)用
NSLog(@"=========>%@",x);
}];
// 信號中的信號發(fā)送一個信號
[signalOfSignals sendNext:signals];
// 信號發(fā)送一個內(nèi)容
[signals sendNext:@"信號發(fā)送信號"];
```
> map的使用:把源信號的值映射成一個新的值纵寝,`map`中的block返回的是一般對象(這里一般用于把源信號里的json數(shù)據(jù)映射成相應(yīng)的model)
```
// 監(jiān)聽文本框內(nèi)容的改變,映射成一個新的值
[[textField.rac_textSignal map:^id(id value) {
// 這里是把文本框的內(nèi)容加上 “Hello RAC” 的前綴
return [NSString stringWithFormat:@"Hello RAC :%@",value];
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
```
> 開發(fā)中店雅,如果信號發(fā)出的不是信號闹啦,映射一般使用`map`,如果信號發(fā)出的是信號窍奋,則使用`flattenMap`。
-
ReactiveCocoa操作方法之組合
-
concat
:按一定順序拼接信號江场,當(dāng)多個信號發(fā)出的時候窖逗,有順序的接收信號
RACSignal * signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"First"]; [subscriber sendCompleted]; return nil; }]; RACSignal * signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"Second"]; [subscriber sendCompleted]; return nil; }]; // 把A拼接到B后 A發(fā)送完成B才會被激活 按順序 RACSignal * concatSignal = [signalA concat:signalB]; [concatSignal subscribeNext:^(id x) { NSLog(@"Concat Signal %@",x); }];
-
then
:用于連接兩個信號,當(dāng)?shù)谝粋€信號完成碎紊,才會連接then
返回的信號樊诺,第一個信號會被忽略掉音同。
RACSignal * thenSignal = [signalA then:^RACSignal *{ return signalB; }]; [thenSignal subscribeNext:^(id x) { // 此處輸出為 Then signal Second 第一個信號會被忽略掉 NSLog(@"Then signal %@",x); }];
-
merge
把多個信號合并為一個信號权均,任何一個信號有新值就會調(diào)用。
RACSignal * mergeSignal = [signalA merge:signalB]; [mergeSignal subscribeNext:^(id x) { NSLog(@"Merge Signal %@",x); }];
-
zipWith
:用于把兩個信號壓縮成一個信號叽赊,只有兩個信號都發(fā)出信號內(nèi)容時,把兩個信號的內(nèi)容合并成一個元組芽唇,才會觸發(fā)壓縮流的next事件取劫。
RACSignal * zipWithSignal = [signalA zipWith:signalB]; [zipWithSignal subscribeNext:^(id x) { NSLog(@"ZipWith Signal %@",x); }];
-
combineLatest
:將多個信號合并起來研侣,并且拿到各個信號的最新的值,必須每個合并的signal至少都有過一次sendNext庶诡,才會觸發(fā)合并的信號。這個方法試了一下扯俱,覺得跟zipWith
是相似的喇澡。
RACSignal * combineSignal = [signalA combineLatestWith:signalB]; [combineSignal subscribeNext:^(id x) { NSLog(@"Combine Signal %@",x); }];
-
reduce
:聚合:用于信號發(fā)出的內(nèi)容是元組,把信號發(fā)出元組的值聚合成一個值
// 常見的方法(先組合再聚合)读存。 // 先組合再聚合呕屎,把上面兩個信號聚合在一起。形成一個信號 (兩者都成立才為yes) // 用于登錄頁面秀睛,兩個文本框的內(nèi)容都符合條件,登錄按鈕才會響應(yīng) RACSignal * reduceSignal = [RACSignal combineLatest:@[usernameLengthSignal, passwordLengthSignal] reduce:^id(NSNumber * username , NSNumber * password){ return @(username.boolValue && password.boolValue); }];
-
RAC一些常用的宏
-
RAC()居凶,這個宏的完整寫法是:
RAC(TARGET,[KEYPATH,NIL_VALUE])
使用方法:
RAC(label,text) = self.textField.rac_textSignal; RAC(label,text,@"如果是nil就顯示這里的文字") = self.textField.rac_textSignal;
最常用的宏
RAC()
一般出現(xiàn)在等號左邊,右邊是一個RACSignal
抹估,作用是將一個對象(這里是label)的一個屬性(這里是label的text)和一個RACSignal
綁定弄兜,RACSignal
每產(chǎn)生一個value,都會自動將這個對象的這個屬性設(shè)置為value替饿。如果value是nil,就設(shè)置為第三個參數(shù)踱卵。(上面的代碼的效果是把label的text和textField的文字變動的signal綁定据过, 每當(dāng)textField里面的文字有變化,就給label設(shè)置新的text绳锅。) -
RACObserve(TARGET,KEYPATH)
作用是觀察TARGET的KEYPATH屬性,產(chǎn)生一個
RACSignal
眷柔,相當(dāng)于KVO原朝。RAC(self.outputLabel, text) = RACObserve(self.model, name);
把label的text和model的name綁定,只要name有變化喳坠,label的text也會變化為相應(yīng)的值。
暫時寫這么點吧谢澈。 代碼點擊這里.