iOS ReactiveCocoa基礎(chǔ)使用

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)圖

ReactiveCocoa思維導(dǎo)圖.png

常見(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];
}];
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容