1、ReactiveCocoa簡(jiǎn)介
ReactiveCocoa(簡(jiǎn)稱為RAC),是由Github 開(kāi)源的一個(gè)應(yīng)用于iOS和OS X開(kāi)發(fā)的新框架。RAC具有函數(shù)式編程(FP)和響應(yīng)式編程(RP)的特性。所以,RAC也被描述為函數(shù)響應(yīng)式編程(FRP)框架。 RAC框架的核心類是RACSignal, 所有的消息都是通過(guò)信號(hào)的方式進(jìn)行傳遞,可以簡(jiǎn)單的理解這些信號(hào)就是一連串的狀態(tài),在狀態(tài)發(fā)生改變的時(shí)候,對(duì)應(yīng)的訂閱者就會(huì)收到通知,然后執(zhí)行相應(yīng)的操作。
響應(yīng)式編程思想:不需要考慮調(diào)用順序,只需要知道考慮結(jié)果。類似于蝴蝶效應(yīng),產(chǎn)生一個(gè)事件,會(huì)影響很多東西。這些事件像流一樣的傳播出去,然后影響結(jié)果,借用面向?qū)ο蟮囊痪湓?,萬(wàn)物皆是流。
比如在程序開(kāi)發(fā)中 a = b + c ,賦值之后 b 或者 c 的值變化后,a 的值不會(huì)跟著變化。而采用響應(yīng)式編程,則如果 b 或者 c 的數(shù)值發(fā)生變化,a 的數(shù)值會(huì)同時(shí)發(fā)生變化,即 a 的值與 b 和 c 綁定。
2、ReactiveCocoa主要應(yīng)用場(chǎng)景
UI數(shù)據(jù)綁定
RAC可以方便的綁定任何數(shù)據(jù)流到UI控件上。
用戶交互事件綁定
RAC可以為可交互的UI控件提供了一系列能發(fā)送Signal信號(hào)的方法。
統(tǒng)一的消息傳遞機(jī)制
RAC提供了統(tǒng)一的方法去處理異步的行為,包括delegate方法、blocks回調(diào)、target-action機(jī)制、notifications和KVO。
3、ReactiveCocoa常見(jiàn)類
思維導(dǎo)圖

常見(jiàn)類
1、RACSiganl
信號(hào)類。只是表示當(dāng)數(shù)據(jù)改變時(shí),信號(hào)內(nèi)部會(huì)發(fā)出數(shù)據(jù),它本身不具備發(fā)送信號(hào)的能力,而是交給內(nèi)部一個(gè)訂閱者去發(fā)出。默認(rèn)信號(hào)都是冷信號(hào),也就是值改變了,也不會(huì)觸發(fā)。只有訂閱了這個(gè)信號(hào),這個(gè)信號(hào)才會(huì)變?yōu)闊嵝盘?hào),值改變了才會(huì)觸發(fā)。如何訂閱信號(hào):調(diào)用信號(hào)RACSignal的subscribeNext就能訂閱
RACEmptySignal :空信號(hào),用來(lái)實(shí)現(xiàn) RACSignal 的 +empty 方法;
RACDynamicSignal :動(dòng)態(tài)信號(hào),使用一個(gè) block 來(lái)實(shí)現(xiàn)訂閱行為,我們?cè)谑褂?RACSignal 的 +createSignal: 方法時(shí)創(chuàng)建的就是該類的實(shí)例;
RACErrorSignal :錯(cuò)誤信號(hào),用來(lái)實(shí)現(xiàn) RACSignal 的 +error: 方法;
2、RACSubscriber
表示訂閱者的意思,用于發(fā)送信號(hào),這是一個(gè)協(xié)議,不是一個(gè)類,只要遵守這個(gè)協(xié)議,并且實(shí)現(xiàn)方法才能成為訂閱者。通過(guò) createSignal 創(chuàng)建的信號(hào),都有一個(gè)訂閱者,幫助他發(fā)送數(shù)據(jù)。
3、RACDisposable
用于取消訂閱或者清理資源,當(dāng)信號(hào)發(fā)送完成或者發(fā)送錯(cuò)誤的時(shí)候,就會(huì)自動(dòng)觸發(fā)它,也可以手動(dòng)調(diào)用 [disposable dispose] 觸發(fā)。
RAC使用流程
1、創(chuàng)建信號(hào)
2、訂閱信號(hào)
3、發(fā)送信號(hào)
4、銷毀信號(hào) (需要的時(shí)候)
示例如下:
//1、創(chuàng)建信號(hào)(冷信號(hào))
RACSignal * single = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
//block調(diào)用時(shí)刻:每當(dāng)有訂閱者訂閱信號(hào),就會(huì)調(diào)用block
//3、發(fā)送信號(hào)
[subscriber sendNext:@"發(fā)送信息"];
//如果不再發(fā)送數(shù)據(jù),最好發(fā)送信號(hào)完成,內(nèi)部會(huì)自動(dòng)調(diào)用[RACDisposable disposable]取消訂閱
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
//block調(diào)用時(shí)刻:當(dāng)信號(hào)發(fā)送完成或者發(fā)送錯(cuò)誤,就會(huì)自動(dòng)執(zhí)行這個(gè)block,取消訂閱。執(zhí)行完Block后,當(dāng)前信號(hào)就不在被訂閱了
NSLog(@"信號(hào)被銷毀");
}];
}];
//2、訂閱信號(hào)(該信號(hào)變成熱信號(hào))
RACDisposable *disposable = [single subscribeNext:^(id _Nullable x) {
//block調(diào)用時(shí)刻:每當(dāng)有信號(hào)發(fā)送數(shù)據(jù),就會(huì)調(diào)用該方法
NSLog(@"接收到數(shù)據(jù):%@",x);
}];
//主動(dòng)觸發(fā)取消訂閱
//[disposable dispose];
4、RACSubject
上面說(shuō)到 RACSignal 是不具備發(fā)送信號(hào)的能力的,但是RACSubject這個(gè)類就可以做到訂閱/發(fā)送為一體。
使用場(chǎng)景:通常用來(lái)代替代理。
示例如下:
//1創(chuàng)建信號(hào)
RACSubject * subject = [RACSubject subject];
//2訂閱信號(hào)
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//3發(fā)送數(shù)據(jù)
[subject sendNext:@"發(fā)送數(shù)據(jù)"];
5、RACCommand
RAC中用于處理事件的類,可以把事件如何處理,事件中的數(shù)據(jù)如何傳遞,包裝到這個(gè)類中,他可以很方便的監(jiān)控事件的執(zhí)行過(guò)程。
使用場(chǎng)景:監(jiān)聽(tīng)按鈕點(diǎn)擊、網(wǎng)絡(luò)請(qǐng)求等。
示例如下:
//1、創(chuàng)建命令
RACCommand * loginBtnCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
NSLog(@"接收傳過(guò)來(lái)的登錄請(qǐng)求參數(shù):%@",input);
//創(chuàng)建信號(hào)
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"開(kāi)始請(qǐng)求");
NSLog(@"請(qǐng)求中...");
NSLog(@"請(qǐng)求成功");
NSLog(@"處理數(shù)據(jù)");
//發(fā)送信號(hào)
[subscriber sendNext:@"我是請(qǐng)求到的數(shù)據(jù)"];
//請(qǐng)求完成
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"結(jié)束了");
}];
}];
}];
/*
2、訂閱loginBtnCommand命令事件中的信號(hào)發(fā)出的值
switchToLatest表示的是最新發(fā)送的信號(hào)
*/
[loginBtnCommand.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"接收到的請(qǐng)求數(shù)據(jù):%@",x);
NSLog(@"登錄成功,跳轉(zhuǎn)頁(yè)面");
}];
/*
3、監(jiān)聽(tīng)loginBtnCommand監(jiān)聽(tīng)命令是否執(zhí)行完畢,默認(rèn)會(huì)來(lái)一次,可以直接跳過(guò)
默認(rèn)會(huì)來(lái)一次,可以直接跳過(guò),skip表示跳過(guò)第一次命令)
*/
[[loginBtnCommand.executing skip:1] subscribeNext:^(NSNumber * _Nullable x) {
if ([x boolValue]) {
NSLog(@"正在執(zhí)行中...");
} else {
NSLog(@"執(zhí)行結(jié)束");
}
}];
//4、執(zhí)行命令
[loginBtnCommand execute:@{@"account":@"1234567890",@"password":@"123456"}];
6、RACSequence
RAC中的集合類,用于代替NSArray、NSDictionary。
使用場(chǎng)景:可以使用它來(lái)快速遍歷數(shù)組和字典。
示例如下:
//遍歷數(shù)組
NSArray * arr = @[@"1",@"2",@"3",@"4",@"5"];
/*
第一步: 把數(shù)組轉(zhuǎn)換成集合RACSequence numbers.rac_sequence
第二步: 把集合RACSequence轉(zhuǎn)換RACSignal信號(hào)類 numbers.rac_sequence.signal
第三步: 訂閱信號(hào),激活信號(hào),會(huì)自動(dòng)把集合中的所有值,遍歷出來(lái)。
*/
[arr.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"內(nèi)容:%@",x);
}];
//遍歷字典,遍歷出來(lái)的鍵值對(duì)會(huì)包裝成RACTuple(元組對(duì)象)
NSDictionary *dict = @{@"name":@"xiaoming",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(id x) {
//解包元組(x是元祖)
RACTupleUnpack(NSString *name,NSString *age) = x;
NSLog(@"%@ %@",name,age);
}];
7、RACScheduler
RAC中的隊(duì)列,用GCD封裝的。
示例如下:
//定時(shí)器
@weakify(self)
RACDisposable * disposable = [[RACSignal interval:2 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {
@strongify(self)
NSLog(@"當(dāng)前時(shí)間:%@",x);
//關(guān)閉定時(shí)器
[disposable dispose];
}];
8、RACMulticastConnection
信號(hào)連接類。用于當(dāng)一個(gè)信號(hào),被多次訂閱時(shí),為了保證創(chuàng)建信號(hào)時(shí),避免多次調(diào)用創(chuàng)建信號(hào)中的block,造成副作用,可以使用這個(gè)類處理。RACMulticastConnection通過(guò)RACSignal的-publish或者-muticast:方法創(chuàng)建。
示例如下:
/*
RACMulticastConnection:信號(hào)連接類
一般情況下,信號(hào)被訂閱多少次,信號(hào)創(chuàng)建的block就被調(diào)用多少次。但是實(shí)際開(kāi)發(fā)中,block只需調(diào)用一次就可以了。RACMulticastConnection可以實(shí)現(xiàn)不管訂閱多少次信號(hào),信號(hào)的block只調(diào)用一次。
如下代碼:信號(hào)被訂閱了3次,但是singal里面的block只被調(diào)用一次,即只輸出一次“請(qǐng)求數(shù)據(jù)”
*/
//1、創(chuàng)建信號(hào)
RACSignal * singal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"請(qǐng)求數(shù)據(jù)");
[subscriber sendNext:@"請(qǐng)求數(shù)據(jù)"];
return nil;
}];
//2、把信號(hào)轉(zhuǎn)成連接類
RACMulticastConnection * connection = [singal publish];
//3、訂閱連接類信號(hào)
[connection.signal subscribeNext:^(id _Nullable x) {
NSLog(@"訂閱1:%@",x);
}];
[connection.signal subscribeNext:^(id _Nullable x) {
NSLog(@"訂閱2:%@",x);
}];
[connection.signal subscribeNext:^(id _Nullable x) {
NSLog(@"訂閱3:%@",x);
}];
//4、連接,激活信號(hào)
[connection connect];
9、ReactiveCocoa常見(jiàn)宏
1、RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于給某個(gè)對(duì)象的某個(gè)屬性綁定。
//這里吧label的text屬性綁定到textField改變信號(hào)中,textfield的內(nèi)容發(fā)生改變的時(shí)候就會(huì)發(fā)出信號(hào),label的text就會(huì)跟隨著改變。
RAC(self.label,text) = _textfield.rac_textSignal;
2、RACObserve(self, name):監(jiān)聽(tīng)某個(gè)對(duì)象的某個(gè)屬性,返回的是信號(hào)。相當(dāng)于kvo使用。
//監(jiān)聽(tīng)self的age屬性,x為屬性的信息
[RACObserve(self, age) subscribeNext:^(id _Nullable x) {
NSLog(@"x:%@",x);
}];
3、RACTuplePack:把數(shù)據(jù)包裝成RACTuple(元組類)
4、RACTupleUnpack:把RACTuple(元組類)解包成對(duì)應(yīng)的數(shù)據(jù)
//元組
RACTuple * tuple = RACTuplePack(@1,@2,@3);//使用RACTuplePack宏來(lái)快速創(chuàng)建
NSLog(@"TUPLE:%@",tuple);
//使用RACTupleUnpack宏快速解包
RACTupleUnpack(NSNumber *num1,NSNumber *num2,NSNumber *num3) = tuple;
NSLog(@"num1:%@",num1);
NSLog(@"num2:%@",num2);
NSLog(@"num3:%@",num3);
//使用下標(biāo)的方式來(lái)獲取
NSLog(@"第0個(gè):%@",tuple[0]);
10、 ReactiveCocoa常見(jiàn)用法
1、rac_signalForSelector:用于替代代理。
/*
代替代理
rac_signalForSelector:把調(diào)用某個(gè)對(duì)象的方法的信息轉(zhuǎn)換成信號(hào),調(diào)用這個(gè)方法,就會(huì)發(fā)送信號(hào)。
當(dāng)redView中的testButton按鈕被點(diǎn)擊了(即調(diào)用了testButtonClick),就會(huì)發(fā)出信號(hào)
*/
[[redView rac_signalForSelector:@selector(testButtonClick:)] subscribeNext:^(id x) {
NSLog(@"redView中的testButton按鈕被點(diǎn)擊了");
}];
2、rac_valuesAndChangesForKeyPath:代替KVO,用于監(jiān)聽(tīng)某個(gè)對(duì)象的屬性改變。
/*
KVO
把監(jiān)聽(tīng)redView的center屬性改變轉(zhuǎn)換成信號(hào),只要值改變就會(huì)發(fā)送信號(hào)
x為屬性的信息
*/
[[redView rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
NSLog(@"center:%@",x);
}];
3、rac_signalForControlEvents:用于監(jiān)聽(tīng)某個(gè)事件。
/*
監(jiān)聽(tīng)事件
把按鈕點(diǎn)擊事件轉(zhuǎn)換為信號(hào),點(diǎn)擊按鈕,就會(huì)發(fā)送信號(hào)
x為Button的信息
*/
[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"按鈕被點(diǎn)擊了");
}];
4、rac_addObserverForName:用于監(jiān)聽(tīng)某個(gè)通知。
/*
代替通知
把監(jiān)聽(tīng)到的通知轉(zhuǎn)換信號(hào)
*/
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
NSLog(@"鍵盤彈出");
}];
5、rac_textSignal:監(jiān)聽(tīng)文本框文字改變。
//監(jiān)聽(tīng)文本框的文字改變
[self.passwordTextField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
NSLog(@"密碼框輸入的內(nèi)容%@",x);
}];
11、ReactiveCocoa組合用法
1、concat:按一定順序拼接信號(hào),當(dāng)多個(gè)信號(hào)發(fā)出的時(shí)候,有順序的接收信號(hào)
//當(dāng)需要按順序執(zhí)行的時(shí)候: 先執(zhí)行C, 在執(zhí)行D
RACSubject *subC = [RACSubject subject];
RACSubject *subD = [RACReplaySubject subject];
NSMutableArray *array2 = [NSMutableArray array];
//訂閱信號(hào)
[[subC concat:subD] subscribeNext:^(id _Nullable x) {
[array2 addObject:x];
}];
//發(fā)送信號(hào)
[subD sendNext:@"D"];
[subC sendNext:@"C"];
[subC sendCompleted];
//輸出: [C, D]
NSLog(@"%@", array2);
2、then:用于連接兩個(gè)信號(hào),當(dāng)?shù)谝粋€(gè)信號(hào)完成,才會(huì)連接then返回的信號(hào)
RACSubject *subjectA = [RACReplaySubject subject];
RACSubject *subjectB = [RACReplaySubject subject];
//發(fā)送信號(hào)
[subjectA sendNext:@"A"];
[subjectA sendCompleted];
[subjectB sendNext:@"B"];
//訂閱信號(hào)
[[subjectA then:^RACSignal * _Nonnull{
return subjectB;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
//這里只會(huì)輸出: B 不會(huì)輸出: A
3、merge:把多個(gè)信號(hào)合并為一個(gè)信號(hào),任何一個(gè)信號(hào)有新值的時(shí)候就會(huì)調(diào)用
// 只要想無(wú)序的整合信號(hào)數(shù)據(jù)
RACSubject *subjectA = [RACSubject subject];
RACSubject *subjectB = [RACSubject subject];
RACSubject *subjectC = [RACSubject subject];
//合并信號(hào)
RACSignal *single = [[subjectA merge:subjectB] merge:subjectC];
//訂閱信號(hào)
[single subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
//發(fā)出消息
[subjectA sendNext:@"A"];
[subjectC sendNext:@"C"];
[subjectB sendNext:@"B"];
//輸出結(jié)果(分別輸出): A, C, B
4、zipWith:把兩個(gè)信號(hào)壓縮成一個(gè)信號(hào),只有當(dāng)兩個(gè)信號(hào)同時(shí)發(fā)出信號(hào)內(nèi)容時(shí),并且把兩個(gè)信號(hào)的內(nèi)容合并成一個(gè)元組,才會(huì)觸發(fā)壓縮流的next事件
// 只要想無(wú)序的整合信號(hào)數(shù)據(jù)
RACSubject *subjectA = [RACSubject subject];
RACSubject *subjectB = [RACSubject subject];
//合并信號(hào)
RACSignal *single = [subjectA zipWith:subjectB];
//訂閱信號(hào)
[single subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
//發(fā)出消息
[subjectA sendNext:@"A"];
[subjectB sendNext:@"B"];
//輸出: 元祖(A, B)
5、combineLatest:將多個(gè)信號(hào)合并起來(lái),并且拿到各個(gè)信號(hào)的最新的值,必須每個(gè)合并的signal至少都有過(guò)一次sendNext,才會(huì)觸發(fā)合并的信號(hào)
6、reduce(聚合):用于信號(hào)發(fā)出的內(nèi)容是元組,把信號(hào)發(fā)出元組的值聚合成一個(gè)值
@weakify(self)
RAC(self.loginButton, enabled) = [RACSignal combineLatest:@[self.phoneTextField.rac_textSignal,self.passwordTextField.rac_textSignal] reduce:^id _Nonnull(NSString * account, NSString * password){
@strongify(self)
if (account.length && (password.length > 5)) {
self.loginButton.backgroundColor = [UIColor blueColor];
return @(YES);
}else{
self.loginButton.backgroundColor = [UIColor lightGrayColor];
return @(NO);
}
}];
7、filter:過(guò)濾,每次信號(hào)發(fā)出,會(huì)先執(zhí)行過(guò)濾條件判斷
[[_accountText.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
//類似手機(jī)號(hào)的輸入, 只有等于11位的時(shí)候才返回true
return value.length == 11;
}] subscribeNext:^(NSString * _Nullable x) {
//這里只會(huì)返回等于11位的字符
NSLog(@"filter = %@", x);
}];
8、ignore:內(nèi)部調(diào)用filter過(guò)濾,忽略掉ignore的值
//當(dāng)88時(shí),下面的log不輸出
[[self.phoneTextField.rac_textSignal ignore:@"88"] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"ignore = %@", x);
}];
9、distinctUntilChanged:當(dāng)上一次的值和當(dāng)前的值有明顯的變化就會(huì)發(fā)出信號(hào),否則會(huì)被忽略掉。常用于UI刷新,即只有兩次數(shù)據(jù)不一樣才需要刷新UI。
//創(chuàng)建信號(hào)
RACSubject *subject = [RACSubject subject];
//訂閱
[[subject distinctUntilChanged] subscribeNext:^(id _Nullable x) {
NSLog(@"distinctUntilChanged = %@", x);
}];
[subject sendNext:@12];
[subject sendNext:@12];
[subject sendNext:@23];
/*
輸出結(jié)果:只會(huì)輸出兩次
distinctUntilChanged = 12
distinctUntilChanged = 23
*/
10、take:從開(kāi)始一共取N次的信號(hào), 當(dāng)遇到sendCompleted語(yǔ)句執(zhí)行時(shí), 會(huì)提前停止發(fā)送信號(hào)
RACSubject *subject1 = [RACSubject subject];
[[subject1 take:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
[subject1 sendNext:@1];
[subject1 sendNext:@2];
[subject1 sendNext:@3];
//輸出: 1, 2
//如果上面發(fā)送信號(hào)的代碼調(diào)整為
[subject1 sendNext:@1];
[subject1 sendCompleted];
[subject1 sendNext:@2];
[subject1 sendNext:@3];
//那么輸出結(jié)果將會(huì),只輸出: 1
11、takeLast:取調(diào)用sendCompleted之前的N次信號(hào),前提條件,訂閱者必須調(diào)用sendCompleted,否則不會(huì)執(zhí)行任何操作
RACSubject *subject1 = [RACSubject subject];
[[subject1 takeLast:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
[subject1 sendNext:@1];
[subject1 sendNext:@2];
[subject1 sendNext:@3];
[subject1 sendCompleted];
/*
輸出:
2
3
*/
12、takeUntil:只要傳入的信號(hào)發(fā)送完成或者subject2開(kāi)始發(fā)送信號(hào)的時(shí)候,就不會(huì)再接收信號(hào)的內(nèi)容
RACSubject *subject1 = [RACSubject subject];
RACSubject *subject2 = [RACSubject subject];
[[subject1 takeUntil:subject2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
[subject1 sendNext:@11];
[subject1 sendNext:@12];
// [subject1 sendCompleted];
[subject1 sendNext:@13];
[subject2 sendNext:@"21"];
[subject2 sendNext:@"22"];
//輸出: 11, 12, 13
//當(dāng)sendCompleted取消注釋的時(shí)候, 只會(huì)輸出: 11, 12
13、skip:跳過(guò)N個(gè)信號(hào)后, 再開(kāi)始訂閱信號(hào)
//創(chuàng)建信號(hào)
RACSubject *subject = [RACSubject subject];
//訂閱信號(hào)(要求跳過(guò)2個(gè)信號(hào))
[[subject skip:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
//發(fā)送信號(hào)
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
[subject sendNext:@4];
//因?yàn)樯厦嫣^(guò)了兩個(gè)信號(hào), 所以這里只會(huì)輸出: 3, 4
14、switchToLatest:用于signalOfSignals(信號(hào)的信號(hào)),有時(shí)候信號(hào)也會(huì)發(fā)出信號(hào),會(huì)在signalOfSignals中,獲取signalOfSignals發(fā)送的最新信號(hào)
//信號(hào)的信號(hào)
RACSubject *subject1 = [RACSubject subject];
RACSubject *subject2 = [RACSubject subject];
//獲取信號(hào)中信號(hào)最近發(fā)出信號(hào),訂閱最近發(fā)出的信號(hào)
[[subject1 switchToLatest] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
//subject1發(fā)送subject2信號(hào)
[subject1 sendNext:subject2];
[subject2 sendNext:@"信號(hào)中信號(hào)"];
//最終結(jié)果輸出: "信號(hào)中信號(hào)"
15、timeout:超時(shí), 可以讓一個(gè)信號(hào)在一定時(shí)間后自動(dòng)報(bào)錯(cuò)
//timeout: 超時(shí), 可以讓一個(gè)信號(hào)在一定時(shí)間后自動(dòng)報(bào)錯(cuò)
RACSignal *single = [[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
return nil;
}] timeout:2 onScheduler:[RACScheduler currentScheduler]];
[single subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
} error:^(NSError * _Nullable error) {
//2秒后自動(dòng)調(diào)用
NSLog(@"%@", error);
}];
12、注意
1、系統(tǒng)要求:ReactiveCocoa 要求 OS X 10.8+ 以及 iOS 8.0+。
2、強(qiáng)引用問(wèn)題
@weakify 和@strongify 這個(gè)兩個(gè)宏是為了解決在使用block的時(shí)候強(qiáng)引用問(wèn)題,注意這兩個(gè)宏成對(duì)使用才有效。
@weakify(self)
[[self.forgotPasswordButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
@strongify(self)
//發(fā)送數(shù)據(jù)
[self.forgotPasswordButtonRACSubject sendNext:nil];
}];