ReactiveCocoa(FRP)-進(jìn)階篇

  • 1.ReactiveCocoa常見(jiàn)操作方法介紹

    • 1.1 ReactiveCocoa操作須知

      所有的信號(hào)(RACSignal)都可以進(jìn)行操作處理缘薛,因?yàn)樗胁僮鞣椒ǘ级x在RACStream.h中面徽,而RACSignal繼承RACStream。

  • 1.2. ReactiveCocoa操作思想

    - 運(yùn)用的是Hook(鉤子)思想,Hook是一種用于改變API(應(yīng)用程序編程接口:方法)執(zhí)行結(jié)果的技術(shù).
    - Hook用處:截獲API調(diào)用的技術(shù)。
    - Hook原理:在每次調(diào)用一個(gè)API返回結(jié)果之前膀捷,先執(zhí)行你自己的方法,改變結(jié)果的輸出削彬。
    - RAC開(kāi)發(fā)方式:RAC中核心開(kāi)發(fā)方式全庸,也是**綁定**秀仲,之前的開(kāi)發(fā)方式是賦值,而用RAC開(kāi)發(fā)壶笼,應(yīng)該把重心放在綁定啄育,也就是可以在創(chuàng)建一個(gè)對(duì)象的時(shí)候,就綁定好以后想要做的事情拌消,而不是等賦值之后在去做事情。
    - 列如:把數(shù)據(jù)展示到控件上安券,之前都是重寫(xiě)控件的setModel方法墩崩,用RAC就可以在一開(kāi)始創(chuàng)建控件的時(shí)候,就綁定好數(shù)據(jù)侯勉。
    
  • 1.3 ReactiveCocoa核心方法bind

    • 1.3.1.ReactiveCocoa操作的核心方法是bind(綁定),給RAC中的信號(hào)進(jìn)行綁定鹦筹,只要信號(hào)一發(fā)送數(shù)據(jù),就能監(jiān)聽(tīng)到址貌,從而把發(fā)送數(shù)據(jù)改成自己想要的數(shù)據(jù)铐拐。

    • 1.3.2.在開(kāi)發(fā)中很少使用bind方法,bind屬于RAC中的底層方法练对,RAC已經(jīng)封裝了很多好用的其他方法遍蟋,底層都是調(diào)用bind,用法比bind簡(jiǎn)單.

    • 1.3.3.bind方法簡(jiǎn)單介紹和使用螟凭。


      bind方法簡(jiǎn)單介紹和使用

      假設(shè)想監(jiān)聽(tīng)文本框的內(nèi)容虚青,并且在每次輸出結(jié)果的時(shí)候,都在文本框的內(nèi)容拼接一段文字“輸出:”

      方式一:在返回結(jié)果后螺男,拼接棒厘。
      [_textField.rac_textSignal subscribeNext:^(id x) {

        NSLog(@"輸出:%@",x);
      
        }];
      

      方式二:在返回結(jié)果前,拼接下隧,使用RAC中bind方法做處理奢人。

       bind方法參數(shù):需要傳入一個(gè)返回值是RACStreamBindBlock的block參數(shù)
       RACStreamBindBlock是一個(gè)block的類(lèi)型,返回值是信號(hào)淆院,參數(shù)(value,stop)何乎,因此參數(shù)的block返回值也是一個(gè)block。
      
      RACStreamBindBlock:
      參數(shù)一(value):表示接收到信號(hào)的原始值迫筑,還沒(méi)做處理
      參數(shù)二(*stop):用來(lái)控制綁定Block宪赶,如果*stop = yes,那么就會(huì)結(jié)束綁定。
      返回值:信號(hào)脯燃,做好處理搂妻,在通過(guò)這個(gè)信號(hào)返回出去,一般使用RACReturnSignal,需要手動(dòng)導(dǎo)入頭文件RACReturnSignal.h辕棚。
      

    bind方法使用步驟:

    • 1.傳入一個(gè)返回值RACStreamBindBlock的block欲主。
    • 2.描述一個(gè)RACStreamBindBlock類(lèi)型的bindBlock作為block的返回值邓厕。
    • 3.描述一個(gè)返回結(jié)果的信號(hào),作為bindBlock的返回值扁瓢。
      注意:在bindBlock中做信號(hào)結(jié)果的處理详恼。

    底層實(shí)現(xiàn):

    • 1.源信號(hào)調(diào)用bind,會(huì)重新創(chuàng)建一個(gè)綁定信號(hào)。
    • 2.當(dāng)綁定信號(hào)被訂閱引几,就會(huì)調(diào)用綁定信號(hào)中的didSubscribe昧互,生成一個(gè)bindingBlock。
    • 3.當(dāng)源信號(hào)有內(nèi)容發(fā)出伟桅,就會(huì)把內(nèi)容傳遞到bindingBlock處理敞掘,調(diào)用bindingBlock(value,stop)
    • 4.調(diào)用bindingBlock(value,stop),會(huì)返回一個(gè)內(nèi)容處理完成的信號(hào)(RACReturnSignal)楣铁。
    • 5.訂閱RACReturnSignal玖雁,就會(huì)拿到綁定信號(hào)的訂閱者,把處理完成的信號(hào)內(nèi)容發(fā)送出來(lái)盖腕。

    注意:不同訂閱者赫冬,保存不同的nextBlock,看源碼的時(shí)候溃列,一定要看清楚訂閱者是哪個(gè)劲厌。
    這里需要手動(dòng)導(dǎo)入#import <ReactiveCocoa/RACReturnSignal.h>,才能使用RACReturnSignal哭廉。

    [[_textField.rac_textSignal bind:^RACStreamBindBlock{
    
    // 什么時(shí)候調(diào)用:
    // block作用:表示綁定了一個(gè)信號(hào).
    
    return ^RACStream *(id value, BOOL *stop){
    
        // 什么時(shí)候調(diào)用block:當(dāng)信號(hào)有新的值發(fā)出脊僚,就會(huì)來(lái)到這個(gè)block。
    
        // block作用:做返回值的處理
    
        // 做好處理遵绰,通過(guò)信號(hào)返回出去.
        return [RACReturnSignal return:[NSString stringWithFormat:@"輸出:%@",value]];
    };
    
    }] subscribeNext:^(id x) {
    
          NSLog(@"%@",x);
    
    }];
    
  • 1.4ReactiveCocoa操作方法之映射(flattenMap,Map)

    flattenMap辽幌,Map用于把源信號(hào)內(nèi)容映射成新的內(nèi)容

    • 1.4.1. flattenMap 用于信號(hào)中的信號(hào),把源信號(hào)的內(nèi)容映射成一個(gè)新的信號(hào)椿访,信號(hào)可以是任意類(lèi)型

      flattenMap使用步驟:
      1.傳入一個(gè)block乌企,block類(lèi)型是返回值RACStream,參數(shù)value
      2.參數(shù)value就是源信號(hào)的內(nèi)容成玫,拿到源信號(hào)的內(nèi)容做處理
      3.包裝成RACReturnSignal信號(hào)加酵,返回出去。
      flattenMap底層實(shí)現(xiàn):
      0.flattenMap內(nèi)部調(diào)用bind方法實(shí)現(xiàn)的,flattenMap中block的返回值哭当,會(huì)作為bind中bindBlock的返回值猪腕。
      1.當(dāng)訂閱綁定信號(hào),就會(huì)生成bindBlock钦勘。
      2.當(dāng)源信號(hào)發(fā)送內(nèi)容陋葡,就會(huì)調(diào)用bindBlock(value, *stop)
      3.調(diào)用bindBlock,內(nèi)部就會(huì)調(diào)用flattenMap的block彻采,flattenMap的block作用:就是把處理好的數(shù)據(jù)包裝成信號(hào)腐缤。
      4.返回的信號(hào)最終會(huì)作為bindBlock中的返回信號(hào)捌归,當(dāng)做bindBlock的返回信號(hào)。
      5.訂閱bindBlock的返回信號(hào)岭粤,就會(huì)拿到綁定信號(hào)的訂閱者惜索,把處理完成的信號(hào)內(nèi)容發(fā)送出來(lái)。

      代碼:

      //1.創(chuàng)建信號(hào)
        RACSubject *subject =[RACSubject subject];
      //2.綁定信號(hào)
        [[subject flattenMap:^RACStream *(id value) {
      // block 只要原信號(hào)發(fā)送內(nèi)容就會(huì)調(diào)用
      // value 就是源信號(hào)發(fā)送的內(nèi)容
      
         NSLog(@"11---%@",[NSThread currentThread]);
      
         value = [NSString stringWithFormat:@"JK %@",value];
      
       // 返回信號(hào)用來(lái)包裝成修改內(nèi)容的值
           return [RACReturnSignal return:value];
       }] subscribeNext:^(id x) {
      
       //3.訂閱信號(hào),flattenMap中返回的是什么信號(hào),訂閱的就是什么信號(hào)
      
         NSLog(@"%@",x);
      
          NSLog(@"22---%@",[NSThread currentThread]);
      
       }];
      
       //4.源信號(hào)發(fā)送信號(hào)
      
       [subject sendNext:@"123"];
      
flattenMap
  • 1.4.2.map簡(jiǎn)單使用
    Map作用:把源信號(hào)的值映射成一個(gè)新的值

    map使用步驟:

    • 1.傳入一個(gè)block,類(lèi)型是返回對(duì)象剃浇,參數(shù)是value
    • 2.value就是源信號(hào)的內(nèi)容巾兆,直接拿到源信號(hào)的內(nèi)容做處理
    • 3.把處理好的內(nèi)容,直接返回就好了虎囚,不用包裝成信號(hào)臼寄,返回的值,就是映射的值溜宽。

    Map底層實(shí)現(xiàn):

    • 0.Map底層其實(shí)是調(diào)用flatternMap,Map中block中的返回的值會(huì)作為flatternMap中block中的值。
    • 1.當(dāng)訂閱綁定信號(hào)质帅,就會(huì)生成bindBlock适揉。
    • 2.當(dāng)源信號(hào)發(fā)送內(nèi)容,就會(huì)調(diào)用bindBlock(value, *stop)
    • 3.調(diào)用bindBlock煤惩,內(nèi)部就會(huì)調(diào)用flattenMap的block
    • 4.flattenMap的block內(nèi)部會(huì)調(diào)用Map中的block嫉嘀,把Map中的block返回的內(nèi)容包裝成返回的信號(hào)。
    • 5.返回的信號(hào)最終會(huì)作為bindBlock中的返回信號(hào)魄揉,當(dāng)做bindBlock的返回信號(hào)剪侮。
    • 6.訂閱bindBlock的返回信號(hào),就會(huì)拿到綁定信號(hào)的訂閱者洛退,把處理完成的信號(hào)內(nèi)容發(fā)送出來(lái)瓣俯。

    代碼

    //1.創(chuàng)建信號(hào)
        RACSubject *subject =[RACSubject subject];
    //2.綁定信號(hào)
        [[subject map:^id(id value) {
    
    // 返回的內(nèi)容就是你要映射的值
       value = [NSString stringWithFormat:@"JK:%@",value];
    
       return value;
    
       }]subscribeNext:^(id x) {
    
          NSLog(@"映射之后的值= %@",x);
    
       }];
    
     //4.源信號(hào)發(fā)送信號(hào)
     [subject sendNext:@"123"];
    
Map簡(jiǎn)單使用
  • 1.4.3.FlatternMap和Map的區(qū)別

    • 1.FlatternMap中的Block返回信號(hào)。
    • 2.Map中的Block返回對(duì)象兵怯。
    • 3.開(kāi)發(fā)中彩匕,如果信號(hào)發(fā)出的值不是信號(hào),映射一般使用Map
    • 4.開(kāi)發(fā)中媒区,如果信號(hào)發(fā)出的值是信號(hào)驼仪,映射一般使用FlatternMap。
  • 1.4.3.總結(jié):signalOfsignals(信號(hào)中的信號(hào))用FlatternMap**

     // 創(chuàng)建信號(hào)中的信號(hào)
     RACSubject *signalOfsignals = [RACSubject subject];
     RACSubject *signal = [RACSubject subject];
     // 創(chuàng)建訂閱者
     [[signalOfsignals flattenMap:^RACStream *(id value) {
    
         // 當(dāng)signalOfsignals的signals發(fā)出信號(hào)才會(huì)調(diào)用
    
        return value;
    
     }] subscribeNext:^(id x) {
    
      // 只有signalOfsignals的signal發(fā)出信號(hào)才會(huì)調(diào)用袜漩,因?yàn)閮?nèi)部訂閱了bindBlock中返回的信號(hào)绪爸,也就是flattenMap返回的信號(hào)。
      // 也就是flattenMap返回的信號(hào)發(fā)出內(nèi)容宙攻,才會(huì)調(diào)用奠货。
    
       NSLog(@"%@aaa",x);
    }];
    
    // 信號(hào)的信號(hào)發(fā)送信號(hào)
     [signalOfsignals sendNext:signal];
    
    // 信號(hào)發(fā)送內(nèi)容
    [signal sendNext:@1];
    
signalOfsignals(*信號(hào)中的信號(hào)*)用FlatternMap**
  • 1.4.4.信號(hào)中的信號(hào)創(chuàng)建訂閱者的3種方式
信號(hào)中的信號(hào)創(chuàng)建訂閱者的3種方式
// 1.創(chuàng)建信號(hào)中的信號(hào)
RACSubject *signalOfsignals = [RACSubject subject];
RACSubject *signal = [RACSubject subject];

//2.創(chuàng)建訂閱者的種方式

   //第1種方式
[signalOfsignals.switchToLatest subscribeNext:^(id x) {
    
    
    NSLog(@"%@",x);
}];

// 第2種方式
[signalOfsignals subscribeNext:^(RACSignal *x) {
    
    [x subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
        
    }];
    
}];

 // 第3種方式
[[signalOfsignals flattenMap:^RACStream *(id value) {
    
    // 當(dāng)signalOfsignals的signals發(fā)出信號(hào)才會(huì)調(diào)用
    
    return value;
    
}] subscribeNext:^(id x) {
    
    // 只有signalOfsignals的signal發(fā)出信號(hào)才會(huì)調(diào)用,因?yàn)閮?nèi)部訂閱了bindBlock中返回的信號(hào)粘优,也就是flattenMap返回的信號(hào)仇味。
    // 也就是flattenMap返回的信號(hào)發(fā)出內(nèi)容呻顽,才會(huì)調(diào)用。
    
    //5.打印信號(hào)發(fā)送的內(nèi)容(可以進(jìn)行修改)
    
    NSLog(@"%@aaa",x);
}];

// 3.信號(hào)的信號(hào)發(fā)送信號(hào)
[signalOfsignals sendNext:signal];

// 4.信號(hào)發(fā)送內(nèi)容
[signal sendNext:@1];
  • 1.5 ReactiveCocoa操作方法之組合

    • 1.5.1.concat:按一定順序拼接信號(hào)丹墨,當(dāng)多個(gè)信號(hào)發(fā)出的時(shí)候廊遍,有順序的接收信號(hào)。

      RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
      [subscriber sendNext:@1];
      
      [subscriber sendCompleted];
      
         return nil;
      }];
      RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
         [subscriber sendNext:@2];
      
         return nil;
      }];
      
      // 把signalA拼接到signalB后贩挣,signalA發(fā)送完成喉前,signalB才會(huì)被激活。
      RACSignal *concatSignal = [signalA concat:signalB];
      
      // 以后只需要面對(duì)拼接信號(hào)開(kāi)發(fā)王财。
      // 訂閱拼接的信號(hào)卵迂,不需要單獨(dú)訂閱signalA,signalB
      // 內(nèi)部會(huì)自動(dòng)訂閱绒净。
      // 注意:第一個(gè)信號(hào)必須發(fā)送完成见咒,第二個(gè)信號(hào)才會(huì)被激活
      [concatSignal subscribeNext:^(id x) {
      
           NSLog(@"%@",x);
      
      }];
      

    注意:第一個(gè)信號(hào)必須發(fā)送完成[subscriber sendCompleted];,第二個(gè)信號(hào)才會(huì)被激活,按順序打印出來(lái).(前后按順序?qū)崿F(xiàn),打印)

    concat底層實(shí)現(xiàn):

      -  1.當(dāng)拼接信號(hào)被訂閱挂疆,就會(huì)調(diào)用拼接信號(hào)的didSubscribe
      -  2.didSubscribe中改览,會(huì)先訂閱第一個(gè)源信號(hào)(signalA)
      -  3.會(huì)執(zhí)行第一個(gè)源信號(hào)(signalA)的didSubscribe
      -  4.第一個(gè)源信號(hào)(signalA)didSubscribe中發(fā)送值,就會(huì)調(diào)用第一個(gè)源信號(hào)(signalA)訂閱者的nextBlock,通過(guò)拼接信號(hào)的訂閱者把值發(fā)送出來(lái).
      -  5.第一個(gè)源信號(hào)(signalA)didSubscribe中發(fā)送完成缤言,就會(huì)調(diào)用第一個(gè)源信號(hào)(signalA)訂閱者的completedBlock,訂閱第二個(gè)源信號(hào)(signalB)這時(shí)候才激活(signalB)宝当。
      -  6.訂閱第二個(gè)源信號(hào)(signalB),執(zhí)行第二個(gè)源信號(hào)(signalB)的didSubscribe
      -  7.第二個(gè)源信號(hào)(signalA)didSubscribe中發(fā)送值,就會(huì)通過(guò)拼接信號(hào)的訂閱者把值發(fā)送出來(lái).
    
    • 1.5.2.then:用于連接兩個(gè)信號(hào),當(dāng)?shù)谝粋€(gè)信號(hào)完成胆萧,才會(huì)連接then返回的信號(hào)

      then:用于連接兩個(gè)信號(hào)庆揩,當(dāng)?shù)谝粋€(gè)信號(hào)完成,才會(huì)連接then返回的信號(hào)
      注意使用then跌穗,之前信號(hào)的值會(huì)被忽略掉.(忽略掉前面的,只打印后面的)
      底層實(shí)現(xiàn):
      1订晌、先過(guò)濾掉之前的信號(hào)發(fā)出的值。
      2蚌吸、使用concat連接then返回的信號(hào)腾仅。

      then代碼
      [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

          [subscriber sendNext:@1];
          [subscriber sendCompleted];
         return nil;
       }] then:^RACSignal *{
           return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@2];
        return nil;
         }];
       }] subscribeNext:^(id x) {
      
         // 只能接收到第二個(gè)信號(hào)的值,也就是then返回信號(hào)的值
         NSLog(@"%@",x);
      }];
      
    • 1.5.3.merge:把多個(gè)信號(hào)合并為一個(gè)信號(hào)套利,任何一個(gè)信號(hào)有新值的時(shí)候就會(huì)調(diào)用

      merge:把多個(gè)信號(hào)合并成一個(gè)信號(hào)(沒(méi)有順序)

      //創(chuàng)建多個(gè)信號(hào)
      RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
         [subscriber sendNext:@1];
      
         return nil;
      }];
      
      RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
         [subscriber sendNext:@2];
      
         return nil;
      }];
      
      // 合并信號(hào),任何一個(gè)信號(hào)發(fā)送數(shù)據(jù)推励,都能監(jiān)聽(tīng)到.
      RACSignal *mergeSignal = [signalA merge:signalB];
      
          [mergeSignal subscribeNext:^(id x) {
      
          NSLog(@"%@",x);
      
      }];
      

    merge底層實(shí)現(xiàn):
    - 1.合并信號(hào)被訂閱的時(shí)候,就會(huì)遍歷所有信號(hào)肉迫,并且發(fā)出這些信號(hào)验辞。
    - 2.每發(fā)出一個(gè)信號(hào),這個(gè)信號(hào)就會(huì)被訂閱
    - 3.也就是合并信號(hào)一被訂閱喊衫,就會(huì)訂閱里面所有的信號(hào)跌造。
    - 4.只要有一個(gè)信號(hào)被發(fā)出就會(huì)被監(jiān)聽(tīng)。

    • 1.5.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事件::----夫妻關(guān)系

       RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
           [subscriber sendNext:@1];
           return nil;
        }];
      
       RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
            [subscriber sendNext:@2];
            return nil;
       }];
      
      // 壓縮信號(hào)A,信號(hào)B
      RACSignal *zipSignal = [signalA zipWith:signalB];
      
      [zipSignal subscribeNext:^(id x) {
      
           NSLog(@"%@",x);
      }];
      
zipWith
底層實(shí)現(xiàn):
  - 1.定義壓縮信號(hào)违施,內(nèi)部就會(huì)自動(dòng)訂閱signalA互纯,signalB
  - 2.每當(dāng)signalA或者signalB發(fā)出信號(hào),就會(huì)判斷signalA磕蒲,signalB有沒(méi)有發(fā)出個(gè)信號(hào)留潦,有就會(huì)把最近發(fā)出的信號(hào)都包裝成元組發(fā)出。
  • 1.5.5.combineLatest(重要)
    combineLatest:將多個(gè)信號(hào)合并起來(lái)辣往,并且拿到各個(gè)信號(hào)的最新的值,必須每個(gè)合并的signal至少都有過(guò)一次sendNext兔院,才會(huì)觸發(fā)合并的信號(hào)

    RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    
       [subscriber sendNext:@1];
    
       return nil;
    }];
    
    RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    
       [subscriber sendNext:@2];
    
       return nil;
    }];
    
    // 把兩個(gè)信號(hào)組合成一個(gè)信號(hào),跟zip一樣,沒(méi)什么區(qū)別
    RACSignal *combineSignal = [signalA combineLatestWith:signalB];
    
       [combineSignal subscribeNext:^(id x) {
    
        NSLog(@"%@",x);
    }];
    

    combineLatest底層實(shí)現(xiàn)

    • 1.當(dāng)組合信號(hào)被訂閱站削,內(nèi)部會(huì)自動(dòng)訂閱signalA坊萝,signalB,必須兩個(gè)信號(hào)都發(fā)出內(nèi)容,才會(huì)被觸發(fā)许起。
    • 2.并且把兩個(gè)信號(hào)組合成元組發(fā)出屹堰。


      combineLatest
  • 1.6 ReactiveCocoa操作方法之過(guò)濾

    • 1.6.1.filter過(guò)濾信號(hào),使用它可以獲取滿(mǎn)足條件的信號(hào)
    filter過(guò)濾信號(hào)
        #pragma mark filter
        -(void)filter
        {
             // 過(guò)濾:
            // 每次信號(hào)發(fā)出街氢,會(huì)先執(zhí)行過(guò)濾條件判斷.
           [[_textField.rac_textSignal filter:^BOOL(NSString *value) {
               return value.length > 3;
           }] subscribeNext:^(id x) {
      
              NSLog(@"%@",x);
           }];
        }
    
    • 1.6.2.ignore:忽略完某些值的信號(hào)
    ignore:忽略完某些值的信號(hào)
      // ignore: 忽略一些值
      // ignoreValues: 忽略所有的值
    
      //1.創(chuàng)建信號(hào)
      RACSubject *subject = [RACSubject subject];
    
      //2.忽略一些
      RACSignal *ignoreSignal = [subject ignore:@12];//ignore相當(dāng)于判斷一下
    
      //3.訂閱信號(hào)
      [ignoreSignal subscribeNext:^(id x) {
      
      //5.打印果略后的數(shù)據(jù)
         NSLog(@"%@",x);
      }];
    
      //4.發(fā)送數(shù)據(jù)
      [subject sendNext:@"1"];
    
    • 1.6.3.take:從開(kāi)始一共取N次的信號(hào)


      take:從開(kāi)始一共取N次的信號(hào)
       // 1、創(chuàng)建信號(hào)
       RACSubject *signal = [RACSubject subject];
      
       // 2睦袖、處理信號(hào)珊肃,訂閱信號(hào)
       [[signal take:2] subscribeNext:^(id x) {
      
              NSLog(@"%@",x);
       }];
      
       // 3.發(fā)送信號(hào)
       [signal sendNext:@1];
      
       [signal sendNext:@2];
      
       [signal sendNext:@3];
      
    • 1.6.4.takeLast:取最后N次的信號(hào),前提條件,訂閱者必須調(diào)用完成馅笙,因?yàn)橹挥型瓿陕浊牵椭揽偣灿卸嗌傩盘?hào)

      takeLast:取最后N次的信號(hào)

      // 1、創(chuàng)建信號(hào)
      RACSubject *signal = [RACSubject subject];
      
      // 2董习、處理信號(hào)烈和,訂閱信號(hào)
      [[signal takeLast:2] subscribeNext:^(id x) {
      
            NSLog(@"%@",x);
      }];
      
      // 3.發(fā)送信號(hào)
      [signal sendNext:@1];
      
      [signal sendNext:@2];
      
      [signal sendNext:@3];
      
      // 必須設(shè)置發(fā)送完成
      [signal sendCompleted];
      
    • 1.6.5.takeUntil:(RACSignal *):獲取信號(hào)直到執(zhí)行完這個(gè)信號(hào),只要傳入信號(hào)發(fā)送完成后或者發(fā)送任意數(shù)據(jù),就不能再接受源信號(hào)的內(nèi)容

      • 監(jiān)聽(tīng)文本框的改變,知道當(dāng)前對(duì)象被銷(xiāo)毀

         [_textField.rac_textSignal takeUntil:self.rac_willDeallocSignal];
        

    信號(hào)處理


    takeUntil
      // takeUntil: 只要傳入信號(hào)發(fā)送完成后或者發(fā)送任意數(shù)據(jù),就不能再接受源信號(hào)的內(nèi)容
    
      // 1皿淋、創(chuàng)建信號(hào)
       RACSubject *signal = [RACSubject subject];
       RACSubject *subject = [RACSubject subject];
    
      // 2招刹、處理信號(hào),訂閱信號(hào)
      [[signal takeUntil:subject] subscribeNext:^(id x) {
      
             NSLog(@"%@",x);
       }];
    
       // 3.發(fā)送信號(hào)
       [signal sendNext:@1];
    
       [signal sendNext:@2];
    
      // [subject sendCompleted];
         [subject sendNext:@"hello"];
    
       [signal sendNext:@3];
    
    • 1.6.6.distinctUntilChanged:當(dāng)上一次的值和當(dāng)前的值有明顯的變化就會(huì)發(fā)出信號(hào)窝趣,否則會(huì)被忽略掉

       // 過(guò)濾疯暑,當(dāng)上一次和當(dāng)前的值不一樣,就會(huì)發(fā)出內(nèi)容哑舒。
       // 在開(kāi)發(fā)中妇拯,刷新UI經(jīng)常使用,只有兩次數(shù)據(jù)不一樣才需要刷新
       [[_textField.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {
      
             NSLog(@"%@",x);
       }];
      
    distinctUntilChanged

    // 創(chuàng)建信號(hào)
    RACSubject *subject = [RACSubject subject];
    // 訂閱信號(hào)
    [[subject distinctUntilChanged] subscribeNext:^(id x) {

            NSLog(@"%@",x);
      
       }];
    
      [subject sendNext:@"1"];
      [subject sendNext:@"2"];
      [subject sendNext:@"2"];
      [subject sendNext:@"1"];
    
    • 1.6.7.skip:(NSUInteger):跳過(guò)幾個(gè)信號(hào),不接受
      skip:(NSUInteger):跳過(guò)幾個(gè)信號(hào),不接受
  • 1.6.8.switchToLatest:用于signalOfSignals(信號(hào)的信號(hào))洗鸵,有時(shí)候信號(hào)也會(huì)發(fā)出信號(hào)越锈,會(huì)在signalOfSignals中仗嗦,獲取signalOfSignals發(fā)送的最新信號(hào)。

     RACSubject *signalOfSignals = [RACSubject subject];
     RACSubject *signal = [RACSubject subject];
     [signalOfSignals sendNext:signal];
     [signal sendNext:@1];
    
     // 獲取信號(hào)中信號(hào)最近發(fā)出信號(hào)甘凭,訂閱最近發(fā)出的信號(hào)稀拐。
     // 注意switchToLatest:只能用于信號(hào)中的信號(hào)
         [signalOfSignals.switchToLatest subscribeNext:^(id x) {
    
           NSLog(@"%@",x);
        }];
    
  • 1.7 ReactiveCocoa操作方法之秩序

    • doNext: 執(zhí)行Next之前,會(huì)先執(zhí)行這個(gè)Block

    • doCompleted: 執(zhí)行sendCompleted之前对蒲,會(huì)先執(zhí)行這個(gè)Block

      [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
             [subscriber sendNext:@1];
             [subscriber sendCompleted];
              return nil;
        }] doNext:^(id x) {
         // 執(zhí)行[subscriber sendNext:@1];之前會(huì)調(diào)用這個(gè)Block
         NSLog(@"doNext");;
      }] doCompleted:^{
         // 執(zhí)行[subscriber sendCompleted];之前會(huì)調(diào)用這個(gè)Block
         NSLog(@"doCompleted");;
      
      }] subscribeNext:^(id x) {
      
         NSLog(@"%@",x);
      }];
      
  • 1.8 ReactiveCocoa操作方法之線(xiàn)程

    • deliverOn: 內(nèi)容傳遞切換到制定線(xiàn)程中钩蚊,副作用在原來(lái)線(xiàn)程中,把在創(chuàng)建信號(hào)時(shí)block中的代碼稱(chēng)之為副作用。

    • subscribeOn: 內(nèi)容傳遞和副作用都會(huì)切換到制定線(xiàn)程中蹈矮。

  • 1.9 ReactiveCocoa操作方法之時(shí)間

    • 1.9.1.timeout:超時(shí)砰逻,可以讓一個(gè)信號(hào)在一定的時(shí)間后,自動(dòng)報(bào)錯(cuò)

      RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          return nil;
      }] timeout:1 onScheduler:[RACScheduler currentScheduler]];
      
      [signal subscribeNext:^(id x) {
      
             NSLog(@"%@",x);
       } error:^(NSError *error) {
            // 1秒后會(huì)自動(dòng)調(diào)用
           NSLog(@"%@",error);
      }];
      
    timeout
    • 1.9.2.interval 定時(shí):每隔一段時(shí)間發(fā)出信號(hào)

       [[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
      
            NSLog(@"%@",x);
       }];
      
interval
  • 1.9.3.delay 延遲發(fā)送next

    delay 延遲發(fā)送next

     [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    
         [subscriber sendNext:@1];
         return nil;
     }] delay:3] subscribeNext:^(id x) {
    
         NSLog(@"%@",x);
     }];
    
  • 1.10. ReactiveCocoa操作方法之重復(fù)

    • 1.10.1.retry重試 :只要失敗泛鸟,就會(huì)重新執(zhí)行創(chuàng)建信號(hào)中的block,直到成功.

       __block int i = 0;
       [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      
          if (i == 10) {
              [subscriber sendNext:@1];
          }else{
              NSLog(@"接收到錯(cuò)誤");
              [subscriber sendError:nil];
          }
          i++;
      
         return nil;
      
         }] retry] subscribeNext:^(id x) {
      
          NSLog(@"%@",x);
      
         } error:^(NSError *error) {
      }];
      
retry重試
  • 1.10.2.replay重放:當(dāng)一個(gè)信號(hào)被多次訂閱,反復(fù)播放內(nèi)容
replay重放

RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

         [subscriber sendNext:@1];
         [subscriber sendNext:@2];
    
         return nil;
     }] replay];

     [signal subscribeNext:^(id x) {
    
          NSLog(@"第一個(gè)訂閱者%@",x);
    
     }];

    [signal subscribeNext:^(id x) {
    
         NSLog(@"第二個(gè)訂閱者%@",x);
    
     }];
  • 1.10.3.throttle節(jié)流:當(dāng)某個(gè)信號(hào)發(fā)送比較頻繁時(shí)蝠咆,可以使用節(jié)流,在某一段時(shí)間不發(fā)送信號(hào)內(nèi)容北滥,過(guò)了一段時(shí)間獲取信號(hào)的最新內(nèi)容發(fā)出

    throttle節(jié)流

      RACSubject *signal = [RACSubject subject];
    
     // 節(jié)流刚操,在一定時(shí)間(1秒)內(nèi),不接收任何信號(hào)內(nèi)容再芋,過(guò)了這個(gè)時(shí)間(1秒)獲取最后發(fā)送的信號(hào)內(nèi)容發(fā)出菊霜。
     [[signal throttle:5] subscribeNext:^(id x) {
    
            NSLog(@"%@",x);
     }];
    
     [signal sendNext:@"我是在5s之后打印的"];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市济赎,隨后出現(xiàn)的幾起案子鉴逞,更是在濱河造成了極大的恐慌,老刑警劉巖司训,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件构捡,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡壳猜,警方通過(guò)查閱死者的電腦和手機(jī)勾徽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)统扳,“玉大人喘帚,你說(shuō)我怎么就攤上這事≈渲樱” “怎么了啥辨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)盯腌。 經(jīng)常有香客問(wèn)我溉知,道長(zhǎng)愉适,這世上最難降的妖魔是什么诗芜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任韧献,我火速辦了婚禮竣贪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玫荣。我一直安慰自己甚淡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布捅厂。 她就那樣靜靜地躺著贯卦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焙贷。 梳的紋絲不亂的頭發(fā)上撵割,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音辙芍,去河邊找鬼啡彬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛故硅,可吹牛的內(nèi)容都是我干的庶灿。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼吃衅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼往踢!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起徘层,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤峻呕,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后惑灵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眼耀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年英支,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哮伟。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡干花,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出楞黄,到底是詐尸還是另有隱情池凄,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布鬼廓,位于F島的核電站肿仑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜尤慰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一馏锡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伟端,春花似錦杯道、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至霜医,卻和暖如春齿拂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背支子。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工创肥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人值朋。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓叹侄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親昨登。 傳聞我的和親對(duì)象是個(gè)殘疾皇子趾代,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容