ReactiveCocoa 基礎(chǔ)整理

本文在最快讓你上手ReactiveCocoa之基礎(chǔ)篇 此基礎(chǔ)上增加了部分自己見解,本文具體用作對ReactiveCocoa的歸納總結(jié),歡迎指導(dǎo)。

RACSignal:信號類,一般表示將來有數(shù)據(jù)傳遞,只要有數(shù)據(jù)改變,信號內(nèi)部接收到數(shù)據(jù),就會馬上發(fā)出數(shù)據(jù)

注意

  • 信號類(RACSignal),只是表示當數(shù)據(jù)改變時,信號內(nèi)部會發(fā)出數(shù)據(jù),它本身不具備發(fā)送信號的能力,而是交給內(nèi)部一個訂閱者去發(fā)出。
  • 默認一個信號都是冷信號,也就是值改變了,也不會觸發(fā),只有訂閱了這個信號,這個信號才會變?yōu)闊嵝盘?,值改變了才會觸發(fā)。
  • 如何訂閱信號:調(diào)用信號RACSignal的subscribeNext就能訂閱。

常見的操作方法

  • flattenMap map 用于把源信號內(nèi)容映射成新的內(nèi)容。
  • concat 組合 按一定順序拼接信號,當多個信號發(fā)出的時候,有順序的接收信號
  • then 用于連接兩個信號,當?shù)谝粋€信號完成,才會連接then返回的信號
  • merge 把多個信號合并為一個信號,任何一個信號有新值的時候就會調(diào)用
  • zipWith 把兩個信號壓縮成一個信號,只有當兩個信號同時發(fā)出信號內(nèi)容時,并且把兩個信號的內(nèi)容合并成一個元組,才會觸發(fā)壓縮流的next事件
  • combineLatest 將多個信號合并起來,并且拿到各個信號的最新的值,必須每個合并的signal至少都有過一次sendNext,才會觸發(fā)合并的信號。
  • reduce 聚合 用于信號發(fā)出的內(nèi)容是元組,把信號發(fā)出元組的值聚合成一個值
  • filter 過濾信號,使用它可以獲取滿足條件的信號
  • ignore 忽略完某些值的信號
  • distinctUntilChanged 當上一次的值和當前的值有明顯的變化就會發(fā)出信號,否則會被忽略掉
  • take 從開始一共取N次的信號
  • takeLast 取最后N次的信號,前提條件,訂閱者必須調(diào)用完成,因為只有完成,就知道總共有多少信號
  • takeUntil 獲取信號直到某個信號執(zhí)行完成
  • skip 跳過幾個信號,不接受
  • switchToLatest 用于signalOfSignals(信號的信號),有時候信號也會發(fā)出信號,會在signalOfSignals中,獲取signalOfSignals發(fā)送的最新信號
  • doNext 執(zhí)行Next之前,會先執(zhí)行這個Block
  • doCompleted 執(zhí)行sendCompleted之前,會先執(zhí)行這個Block
  • timeout 超時,可以讓一個信號在一定的時間后,自動報錯。
  • interval 定時 每隔一段時間發(fā)出信號
  • delay 延遲發(fā)送next
  • retry 重試 只要失敗,就會重新執(zhí)行創(chuàng)建信號中的block,直到成功
  • replay 重放 當一個信號被多次訂閱,反復(fù)播放內(nèi)容
  • throttle 節(jié)流 當某個信號發(fā)送比較頻繁時,可以使用節(jié)流,在某一段時間不發(fā)送信號內(nèi)容,過了一段時間獲取信號的最新內(nèi)容發(fā)出

使用步驟

1. 創(chuàng)建信號 createSignal
2. 訂閱信號,才會激活信號 subscribeNext
3. 發(fā)送信號 sendNext

底層實現(xiàn)

1. 創(chuàng)建信號,首先把didSubscribe保存到信號中,還不會觸發(fā)。
2. 當信號被訂閱,也就是調(diào)用signal的subscribeNext:nextBlock
    2.1 subscribeNext內(nèi)部會調(diào)用signal的didSubscribe   
    2.2 subscribeNext內(nèi)部會創(chuàng)建訂閱者subscriber,并且把nextBlock保存到subscriber中
3.signal的didSubscribe中調(diào)用[subscriber sendNext:@1];
    3.1 sendNext底層其實就是執(zhí)行subscriber的nextBlock 

例子

    // 1.創(chuàng)建信號
    RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        // block調(diào)用時刻:每當有訂閱者訂閱信號,就會調(diào)用block。

        // 3.發(fā)送信號
        [subscriber sendNext:@"OrangeDeveloper"];

        // 如果不在發(fā)送數(shù)據(jù),最好發(fā)送信號完成,內(nèi)部會自動調(diào)用[RACDisposable disposable]取消訂閱信號。
        // 信號什么時候被取消:1.自動取消,當一個信號的訂閱者被銷毀的時候機會自動取消訂閱,2.手動取消
        //除卻[subscriber sendCompleted];外還可在訂閱信號的時候返回一個RACDisposable,利用RACDisposable的disposable方法取消訂閱
        [subscriber sendCompleted];

        return [RACDisposable disposableWithBlock:^{

            // 當信號發(fā)送完成或者發(fā)送錯誤,就會自動執(zhí)行這個block,取消訂閱信號。

            // 執(zhí)行完Block后,當前信號就不在被訂閱了。

            NSLog(@"信號被銷毀");

        }];
    }];

    // 3.訂閱信號,才會激活信號.
    [siganl subscribeNext:^(id x) {
        // 每當有信號發(fā)出數(shù)據(jù),就會調(diào)用block.
        NSLog(@"接收到數(shù)據(jù):%@",x);
    }];
    [siganl subscribeError:^(NSError *error) {
        NSLog(@"訂閱錯誤信號");
    }];
    [siganl subscribeCompleted:^ {
        NSLog(@"訂閱完成信號");
    }];

RACSubscriber:表示訂閱者的意思,用于發(fā)送信號,這是一個協(xié)議,不是一個類,只要遵守這個協(xié)議,并且實現(xiàn)方法才能成為訂閱者。通過create創(chuàng)建的信號,都有一個訂閱者,幫助他發(fā)送數(shù)據(jù)

RACDisposable:用于取消訂閱或者清理資源,當信號發(fā)送完成或者發(fā)送錯誤的時候,就會自動觸發(fā)它

使用場景:不想監(jiān)聽某個信號時,可以通過它主動取消訂閱信號

  • 當訂閱者發(fā)送信號sendNext之后,會執(zhí)行:subscribeNext中的nextBlock。當nextBlock執(zhí)行完畢也就意味著subscribeNext方法返回了RACDisposable對象

注意

  1. 如果不強引用訂閱者對象,默認情況下會自動取消訂閱,我們可以拿到RACDisposable 用disposableWithBlock做清空資源的一些操作了
  2. 如果不希望自動取消訂閱,我們應(yīng)該強引用RACSubscriber * subscriber。在想要取消訂閱的時候用subscribeNext返回的RACDisposable對象去調(diào)用dispose方法

RACSubject:信號提供者,自己可以充當信號,又能發(fā)送信號

使用場景:通常用來代替代理,有了它,就不必要定義代理了。

注意

RACSubject實例進行map操作之后, 發(fā)送完畢一定要調(diào)用sendCompleted, 否則會出現(xiàn)內(nèi)存泄漏; 而RACSignal實例不管是否進行map操作, 不管是否調(diào)用sendCompleted, 都不會出現(xiàn)內(nèi)存泄漏.
原因 : 因為RACSubject是熱信號, 為了保證未來有事件發(fā)生的時候, 訂閱者可以收到信息, 所以需要對持有訂閱者!

使用步驟

1.創(chuàng)建信號 [RACSubject subject],跟RACSiganl不一樣,創(chuàng)建信號時沒有block。
2.訂閱信號 subscribeNext
3.發(fā)送信號 sendNext

底層實現(xiàn)

1.調(diào)用subscribeNext訂閱信號,只是把訂閱者保存起來,并且訂閱者的nextBlock已經(jīng)賦值了
2.調(diào)用sendNext發(fā)送信號,遍歷剛剛保存的所有訂閱者,一個一個調(diào)用訂閱者的nextBlock

例子

    // 1.創(chuàng)建信號
    RACSubject *subject = [RACSubject subject];

    // 2.訂閱信號
    [subject subscribeNext:^(id x) {
        // 當信號發(fā)出新值,就會調(diào)用.
        NSLog(@"訂閱者%@",x);
    }];
    // 3.發(fā)送信號
    [subject sendNext:@"OrangeDeveloper"];
RACSubject替換代理

需求:

  1. 給當前控制器添加一個按鈕,modal到另一個控制器界面
  2. 另一個控制器view中有個按鈕,點擊按鈕,通知當前控制器
步驟一:在第二個控制器.h,添加一個RACSubject代替代理。
@interface TwoViewController : UIViewController

@property (nonatomic, strong) RACSubject *delegateSignal;

@end

步驟二:監(jiān)聽第二個控制器按鈕點擊
@implementation TwoViewController
- (IBAction)notice:(id)sender {
    // 通知第一個控制器,告訴它,按鈕被點了

     // 通知代理
     // 判斷代理信號是否有值
    if (self.delegateSignal) {
        // 有值,才需要通知
        [self.delegateSignal sendNext:nil];
    }
}
@end

步驟三:在第一個控制器中,監(jiān)聽跳轉(zhuǎn)按鈕,給第二個控制器的代理信號賦值,并且監(jiān)聽.
@implementation OneViewController 
- (IBAction)btnClick:(id)sender {

    // 創(chuàng)建第二個控制器
    TwoViewController *twoVc = [[TwoViewController alloc] init];

    // 設(shè)置代理信號
    twoVc.delegateSignal = [RACSubject subject];

    // 訂閱代理信號
    [twoVc.delegateSignal subscribeNext:^(id x) {

        NSLog(@"點擊了通知按鈕");
    }];

    // 跳轉(zhuǎn)到第二個控制器
    [self presentViewController:twoVc animated:YES completion:nil];

}
@end

RACReplaySubject:重復(fù)提供信號類,RACSubject的子類

使用場景:
1.如果一個信號每被訂閱一次,就需要把之前的值重復(fù)發(fā)送一遍,使用重復(fù)提供信號類
2.可以設(shè)置capacity數(shù)量來限制緩存的value的數(shù)量,即只緩充最新的幾個值

使用步驟

1. 創(chuàng)建信號 [RACSubject subject],跟RACSignal不一樣,創(chuàng)建信號時沒有block
2. 可以先訂閱信號,也可以先發(fā)送信號
    2.1 訂閱信號 subscribeNext
    2.2 發(fā)送信號 sendNext

底層實現(xiàn)

1.  調(diào)用sendNext發(fā)送信號,把值保存起來,然后遍歷剛剛保存的所有訂閱者,一個一個調(diào)用訂閱者的nextBlock。
2. 調(diào)用subscribeNext訂閱信號,遍歷保存的所有值,一個一個調(diào)用訂閱者的nextBlock
(如果想當一個信號被訂閱,就重復(fù)播放之前所有值,需要先發(fā)送信號,再訂閱信號。即先保存值,再訂閱值)  

例子

    // 1.創(chuàng)建信號
    RACReplaySubject *replaySubject = [RACReplaySubject subject];

    // 2.發(fā)送信號
    [replaySubject sendNext:@"OrangeDeveloper:1"];
    [replaySubject sendNext:@"OrangeDeveloper:2"];

    // 3.訂閱信號
    [replaySubject subscribeNext:^(id x) {

        NSLog(@"第一個訂閱者接收到的數(shù)據(jù)%@",x);
    }];

    // 訂閱信號
    [replaySubject subscribeNext:^(id x) {

        NSLog(@"第二個訂閱者接收到的數(shù)據(jù)%@",x);
    }];

RACReplaySubject與RACSubject區(qū)別

RACReplaySubject可以先發(fā)送信號,在訂閱信號,RACSubject就不可以

RACTuple:元組類,類似NSArray,用來包裝值

RACSequence:RAC中的集合類,用于代替NSArray,NSDictionary,可以使用它來快速遍歷數(shù)組和字典 (貌似性能比較差不太推薦使用)

RACSequence和RACTuple簡單使用

    // 1.遍歷數(shù)組
    NSArray *numbers = @[@1,@2,@3,@4];

    // 這里其實是三步
    // 第一步: 把數(shù)組轉(zhuǎn)換成集合RACSequence numbers.rac_sequence
    // 第二步: 把集合RACSequence轉(zhuǎn)換RACSignal信號類,numbers.rac_sequence.signal
    // 第三步: 訂閱信號,激活信號,會自動把集合中的所有值,遍歷出來。
    [numbers.rac_sequence.signal subscribeNext:^(id x) {

        NSLog(@"%@",x);
    }];


    // 2.遍歷字典,遍歷出來的鍵值對會包裝成RACTuple(元組對象)
    NSDictionary *dict = @{@"name":@"OrangeDeveloper",@"age":@18};
    [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
        // RACTupleUnpack 宏:專門用來解析元組
        // RACTupleUnpack 括號里:需要解析的元組 宏的參數(shù),填解析的什么樣數(shù)據(jù)
        // 元組里面有幾個值,宏的參數(shù)就必須填幾個
        // 解包元組,會把元組的值,按順序給參數(shù)里面的變量賦值
        RACTupleUnpack(NSString *key,NSString *value) = x;

        // 相當于以下寫法
        // NSString *key = x[0];
        // NSString *value = x[1];

        NSLog(@"%@ %@",key,value);

    }];


    // 3.字典轉(zhuǎn)模型
    
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

    NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
 
    // 3.1 OC寫法
    NSMutableArray *flags = [NSMutableArray array];
    for (NSDictionary *dict in dictArr) {
        FlagItem *item = [FlagItem flagWithDict:dict];
        [flags addObject:item];
    }
    
    // 3.2 RAC寫法
    NSMutableArray *flags = [NSMutableArray array];
    
    _flags = flags;

    // rac_sequence注意點:調(diào)用subscribeNext,并不會馬上執(zhí)行nextBlock,而是會等一會。
    [dictArr.rac_sequence.signal subscribeNext:^(id x) {
        // 運用RAC遍歷字典,x:字典

        FlagItem *item = [FlagItem flagWithDict:x];

        [flags addObject:item];

    }];

    // 3.3 RAC高級寫法:
    
    // map:映射的意思,目的:把原始值value映射成一個新值
    // array: 把集合轉(zhuǎn)換成數(shù)組
    // 底層實現(xiàn):當信號被訂閱,會遍歷集合中的原始值,映射成新值,并且保存到新的數(shù)組里。
    NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {

        return [FlagItem flagWithDict:value];

    }] array];

RACCommand:RAC中用于處理事件的類,可以把事件如何處理,事件中的數(shù)據(jù)如何傳遞,包裝到這個類中,他可以很方便的監(jiān)控事件的執(zhí)行過程

使用場景:監(jiān)聽按鈕點擊,網(wǎng)絡(luò)請求

使用步驟

1. 創(chuàng)建命令 initWithSignalBlock
2. 在signalBlock中,創(chuàng)建RACSignal,并且作為signalBlock的返回值
3. 執(zhí)行命令 execute

注意

1. signalBlock必須要返回一個信號,不能傳nil.
2. 如果不想要傳遞信號,直接創(chuàng)建空的信號[RACSignal empty];
3. RACCommand中信號如果數(shù)據(jù)傳遞完,必須調(diào)用[subscriber sendCompleted],這時命令才會執(zhí)行完畢,否則永遠處于執(zhí)行中。
4. RACCommand需要被強引用,否則接收不到RACCommand中的信號,因此RACCommand中的信號是延遲發(fā)送的。

設(shè)計思想:內(nèi)部signalBlock為什么要返回一個信號,這個信號有什么用

1. 在RAC開發(fā)中,通常會把網(wǎng)絡(luò)請求封裝到RACCommand,直接執(zhí)行某個RACCommand就能發(fā)送請求。
2. 當RACCommand內(nèi)部請求到數(shù)據(jù)的時候,需要把請求的數(shù)據(jù)傳遞給外界,這時候就需要通過signalBlock返回的信號傳遞了。

如何拿到RACCommand中返回信號發(fā)出的數(shù)據(jù)

1. RACCommand有個執(zhí)行信號源executionSignals,這個是signal of signals(信號的信號),意思是信號發(fā)出的數(shù)據(jù)是信號,不是普通的類型。
2. 訂閱executionSignals就能拿到RACCommand中返回的信號,然后訂閱signalBlock返回的信號,就能獲取發(fā)出的值。

例子

    // 1.創(chuàng)建命令
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {

        // 創(chuàng)建空信號,必須返回信號 不允許為nil return [RACSignal empty];

        // 2.創(chuàng)建信號,用來傳遞數(shù)據(jù)
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

            [subscriber sendNext:@"請求數(shù)據(jù)"];

            // 注意:數(shù)據(jù)傳遞完,最好調(diào)用sendCompleted,這時命令才執(zhí)行完畢。
            [subscriber sendCompleted];

            return nil;
        }];

    }];

    // 強引用命令,不要被銷毀,否則接收不到數(shù)據(jù)
    _conmmand = command;

    // 3.訂閱RACCommand中的信號
    [command.executionSignals subscribeNext:^(id x) {

        [x subscribeNext:^(id x) {

            NSLog(@"%@",x);
        }];

    }];
    // RAC高級用法
    // switchToLatest:用于signal of signals,獲取signal of signals發(fā)出的最新信號,也就是可以直接拿到RACCommand中的信號 
    // switchToLatest獲取最新發(fā)送的信號,只能用于信號中信號。
    [command.executionSignals.switchToLatest subscribeNext:^(id x) {

        NSLog(@"%@",x);
    }];

    // 4.監(jiān)聽命令是否執(zhí)行完畢
    // executing 一開始就會監(jiān)聽一次,肯定是 0,一般會忽略(skip)一次 
    // x 非 0 即 1,命令執(zhí)行完畢/正在執(zhí)行
    // 執(zhí)行一次命令,block 中會調(diào)用兩次,正在執(zhí)行->執(zhí)行完畢
    [[command.executing skip:1] subscribeNext:^(id x) {

        if ([x boolValue] == YES) {
            // 正在執(zhí)行
            NSLog(@"正在執(zhí)行");

        }else{
            // 執(zhí)行完成
            NSLog(@"執(zhí)行完成");
        }

    }];
    // 5.執(zhí)行命令
    [self.conmmand execute:@"OrangeDeveloper"];

RACMulticastConnection:用于當一個信號,被多次訂閱時,為了保證創(chuàng)建信號時,避免多次調(diào)用創(chuàng)建信號中的block,造成副作用,可以使用這個類處理

注意

RACMulticastConnection通過RACSignal的publish或者muticast方法創(chuàng)建

使用步驟

1. 創(chuàng)建信號 createSignal
2. 創(chuàng)建連接 RACMulticastConnection *connect = [signal publish];
3. 訂閱信號,注意:訂閱的不在是之前的信號,而是連接的信號。 [connect.signal subscribeNext:nextBlock]
4. 連接 [connect connect]

底層原理

1. 創(chuàng)建connect,connect.sourceSignal -> RACSignal(原始信號)  connect.signal -> RACSubject
2. 訂閱connect.signal,會調(diào)用RACSubject的subscribeNext,創(chuàng)建訂閱者,而且把訂閱者保存起來,不會執(zhí)行block
3. [connect connect]內(nèi)部會訂閱RACSignal(原始信號),并且訂閱者是RACSubject
    3.1 訂閱原始信號,就會調(diào)用原始信號中的didSubscribe
    3.2 didSubscribe,拿到訂閱者調(diào)用sendNext,其實是調(diào)用RACSubject的sendNext
4. RACSubject的sendNext,會遍歷RACSubject所有訂閱者發(fā)送信號
    4.1 因為剛剛第二步,都是在訂閱RACSubject,因此會拿到第二步所有的訂閱者,調(diào)用他們的nextBlock

例子

  • 需求:假設(shè)在一個信號中發(fā)送請求,每次訂閱一次都會發(fā)送請求,這樣就會導(dǎo)致多次請求
  • 解決:使用RACMulticastConnection就能解決
    // 1.創(chuàng)建請求信號 // 普通寫法, 這樣的缺點是:沒訂閱一次信號就得重新創(chuàng)建并發(fā)送請求,這樣很不友好
   RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

       // didSubscribeblock中的代碼都統(tǒng)稱為副作用。
        // 發(fā)送請求---比如afn
        NSLog(@"發(fā)送請求");

        return nil;
    }];
    // 2.訂閱信號
    [signal subscribeNext:^(id x) {

        NSLog(@"接收數(shù)據(jù)");

    }];
    // 2.訂閱信號
    [signal subscribeNext:^(id x) {

        NSLog(@"接收數(shù)據(jù)");

    }];

    // 3.運行結(jié)果,會執(zhí)行兩遍發(fā)送請求,也就是每次訂閱都會發(fā)送一次請求


    // RACMulticastConnection:解決重復(fù)請求問題 比較好的做法。 使用RACMulticastConnection,無論有多少個訂閱者,無論訂閱多少次,我只發(fā)送一個。
    // 1.創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {


        NSLog(@"發(fā)送請求");
        [subscriber sendNext:@"OrangeDeveloper"];

        return nil;
    }];

    // 2.創(chuàng)建連接
    RACMulticastConnection *connect = [signal publish];

    // 3.訂閱信號,
    // 注意:訂閱信號,也不能激活信號,只是保存訂閱者到數(shù)組,必須通過連接,當調(diào)用連接,就會一次性調(diào)用所有訂閱者的sendNext:
    [connect.signal subscribeNext:^(id x) {

        NSLog(@"訂閱者一信號");

    }];

    [connect.signal subscribeNext:^(id x) {

        NSLog(@"訂閱者二信號");

    }];

    // 4.連接,激活信號
    [connect connect];

RACScheduler:RAC中的隊列,用GCD封裝的

RACUnit :表?stream不包含有意義的值,也就是看到這個,可以直接理解為nil

RACEvent: 把數(shù)據(jù)包裝成信號事件(signal event)。它主要通過RACSignal的materialize來使用,然并卵

開發(fā)中常見用法

rac_signalForSelector:用于替代代理

rac_valuesAndChangesForKeyPath:用于監(jiān)聽某個對象的屬性改變

rac_signalForControlEvents:用于監(jiān)聽某個事件

rac_addObserverForName:用于監(jiān)聽某個通知

rac_textSignal:只要文本框發(fā)出改變就會發(fā)出這個信號

rac_liftSelector:withSignalsFromArray:Signals:當傳入的Signals(信號數(shù)組),每一個signal都至少sendNext過一次,就會去觸發(fā)第一個selector參數(shù)的方法

例子

    // 1.代替代理
    // 需求:自定義redView,監(jiān)聽紅色view中按鈕點擊
    // 之前都是需要通過代理監(jiān)聽,給紅色View添加一個代理屬性,點擊按鈕的時候,通知代理做事情
    // rac_signalForSelector:把調(diào)用某個對象的方法的信息轉(zhuǎn)換成信號,就要調(diào)用這個方法,就會發(fā)送信號。
    // 這里表示只要redV調(diào)用btnClick:,就會發(fā)出信號,訂閱就好了。
    [[redV rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
        NSLog(@"點擊紅色按鈕");
    }];

    // 2.KVO
    // 把監(jiān)聽redV的center屬性改變轉(zhuǎn)換成信號,只要值改變就會發(fā)送信號
    // observer:可以傳入nil
    [[redV rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {

        NSLog(@"%@",x);

    }];

    // 3.監(jiān)聽事件
    // 把按鈕點擊事件轉(zhuǎn)換為信號,點擊按鈕,就會發(fā)送信號
    [[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {

        NSLog(@"按鈕被點擊了");
    }];

    // 4.代替通知
    // 把監(jiān)聽到的通知轉(zhuǎn)換信號
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
        NSLog(@"鍵盤彈出");
    }];

    // 5.監(jiān)聽文本框的文字改變
   [_textField.rac_textSignal subscribeNext:^(id x) {

       NSLog(@"文字改變了%@",x);
   }];

   // 6.處理多個請求,都返回結(jié)果的時候,統(tǒng)一做處理.
    RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        // 發(fā)送請求1
        [subscriber sendNext:@"發(fā)送請求1"];
        return nil;
    }];

    RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 發(fā)送請求2
        [subscriber sendNext:@"發(fā)送請求2"];
        return nil;
    }];

    // 使用注意:幾個信號,參數(shù)一的方法就幾個參數(shù),每個參數(shù)對應(yīng)信號發(fā)出的數(shù)據(jù)。
    [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];


}
// 更新UI
- (void)updateUIWithR1:(id)data r2:(id)data1
{
    NSLog(@"更新UI%@  %@",data,data1);
}

常見宏

RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于給某個對象的某個屬性綁定。 把一個對象的某個屬性綁定一個信號,只要發(fā)出信號,就會把信號的內(nèi)容給對象的屬性賦值

// 只要文本框文字改變,就會修改label的文字
RAC(self.labelView,text) = _textField.rac_textSignal;

RACObserve(self, name):監(jiān)聽某個對象的某個屬性,返回的是信號

//例 textField輸入的值賦值給label,監(jiān)聽label文字改變,
RAC(self.label, text) = self.textField.rac_textSignal;
[RACObserve(self.label, text) subscribeNext:^(id x) {
    NSLog(@"====label的文字變了");
}];

@weakify(Obj)和@strongify(Obj),一般兩個都是配套使用,在主頭文件(ReactiveCocoa.h)中并沒有導(dǎo)入,需要自己手動導(dǎo)入,RACEXTScope.h才可以使用。但是每次導(dǎo)入都非常麻煩,只需要在主頭文件自己導(dǎo)入就好了

注意
/**
*  循環(huán)引用問題
*/
@weakify(self)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    @strongify(self)
    NSLog(@"%@",self.view);
    return nil;
}];
_signal = signal;
使用 @weakify(self)和@strongify(self)來避免循環(huán)引用

RACTuplePack:把數(shù)據(jù)包裝成RACTuple(元組類)

// 把參數(shù)中的數(shù)據(jù)包裝成元組
RACTuple *tuple = RACTuplePack(@10,@20);

RACTupleUnpack:把RACTuple(元組類)解包成對應(yīng)的數(shù)據(jù)

// 把參數(shù)中的數(shù)據(jù)包裝成元組
RACTuple *tuple = RACTuplePack(@"OrangeDeveloper",@18);

// 解包元組,會把元組的值,按順序給參數(shù)里面的變量賦值
// name = @"OrangeDeveloper" age = @18
RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 1.ReactiveCocoa簡介 ReactiveCocoa(簡稱為RAC),是由Github開源的一個應(yīng)用于i...
    清蘂翅膀的技術(shù)閱讀 2,080評論 0 1
  • RAC使用測試Demo下載:github.com/FuWees/WPRACTestDemo 1.ReactiveC...
    FuWees閱讀 6,651評論 3 10
  • 1.ReactiveCocoa常見操作方法介紹。 1.1 ReactiveCocoa操作須知 所有的信號(RACS...
    萌芽的冬天閱讀 1,139評論 0 5
  • 1.ReactiveCocoa簡介 ReactiveCocoa(簡稱為RAC),是由Github開源的一個應(yīng)用于i...
    愛睡覺的魚閱讀 1,220評論 0 1
  • 抺掉幾千年傳說中牛郎織女的陰影 用熱烈的心態(tài)擁抱太陽 只要倆情相悅,就大膽地發(fā)起愛的沖鋒 展開愛的翅膀,在愛的天空...
    譚二閱讀 436評論 0 4

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