ReactiveCocoa 個人學習筆記記錄(一)

WechatIMG7.jpeg

之前就一直在看ReactiveCocoa 相關知識 但是有感覺每次看完收貨甚微靴庆,且感覺零零散散 颁独,本blog 僅僅是記錄自己的學習過程

文章目錄

  • 1 ReactiveCocoa 介紹
  • 2 ReactiveCocoa的應用場景
  • 3 ReactiveCocoa 被描述為函數(shù)式響應編程(FRP)框架
  • 4 如何添加ReactiveCocoa
  • 5 分析ReactiveCocoa中的常見類
    • 5-1 RACSignal:信號類
    • 5-2 RACSubscriber:訂閱者
    • 5-3 RACDisposable:取消訂閱
    • 5-4 RACSubject:信號提供者可發(fā)信號可充當信號
    • 5-5 RACTuple:元祖類 類似NSArray用來包裝值
    • 5-6 RACSequence (Sequence:序列排序) :RAC中的集合類 用于代替NSArray 和 NSDictionary 可以使用它來快速遍歷數(shù)組和字典
    • 5-7 RACCommand :RAC中用于處理事件的類, 可以吧事件如何處理,事件中的數(shù)據(jù)如何傳遞矮锈,包裝到這個類中 他可以很方便的監(jiān)控事件的執(zhí)行過程
    • 5-8 RACMulticastConnection 用于當一個信號被多次訂閱是為了保證創(chuàng)建信號時 避免多次調用創(chuàng)建信號中的block 造成副作用 可以使用這個類創(chuàng)建
  • 5-9 RACScheduler :RAC中的隊列 用GCD封裝的
  • 5-10 RACUnit :表示Stream不包含有意義的值 也就是看到這個 可以直接理解為nil
  • 6 ReactiveCocoa 開發(fā)中常見的用法
  • 6-1 代替代理
  • 6-2 代替KVO
  • 6-3 監(jiān)聽事件
  • 6-4 代替通知
  • 6-5 監(jiān)聽文本框文字的改變
  • 6-6 處理多個請求 都返回結果的時候統(tǒng)一做處理
  • 6-7 定時器
  • 7 ReactiveCocoa 開發(fā)中常見的用法
  • 7-1 RAC(TARGET, ...) 用于給某個對象的某個屬性綁定
  • 7-2 RACObserve(TARGET, KEYPATH) 監(jiān)聽某個對象的某個屬性 返回的是信號
  • 7-3 RACTuplePack 把數(shù)據(jù)包裝成RACTuple (元祖類) RACTupleUnpack 把元祖解包成對應的數(shù)據(jù)

1 ReactiveCocoa 介紹

ReactiveCocoa(其簡稱為RAC)是由Github 開源的一個應用于iOS和OS X開發(fā)的新框架。RAC具有函數(shù)式編程和響應式編程的特性

2 ReactiveCocoa的應用場景

對于一個應用來說睁蕾,絕大部分的時間都是在等待某些事件的發(fā)生或響應某些狀態(tài)的變化苞笨,比如用戶的觸摸事件、應用進入后臺子眶、網(wǎng)絡請求成功刷新界面等等猫缭,而維護這些狀態(tài)的變化,常常會使代碼變得非常復雜壹店,難以擴展猜丹。而 ReactiveCocoa 給出了一種非常好的解決方案,它使用信號來代表這些異步事件硅卢,提供了一種統(tǒng)一的方式來處理所有異步的行為射窒,包括代理方法、block 回調将塑、target-action 機制脉顿、通知、KVO 等

3 ReactiveCocoa 被描述為函數(shù)式響應編程(FRP)框架

ReactiveCocoa結合了幾種編程風格

函數(shù)式編程(Functional Programming)

是把操作盡量寫成一系列嵌套的函數(shù)或者方法調用点寥。
函數(shù)式編程特點:每個方法必須有返回值(本身對象),把函數(shù)或者Block當做參數(shù),block參數(shù)(需要操作的值)block返回值(操作結果)

代表: ReactiveCocoa

響應式編程(Reactive Programming )

不需要考慮調用順序艾疟,只需要知道考慮結果,類似于蝴蝶效應敢辩,產(chǎn)生一個事件蔽莱,會影響很多東西,這些事件像流一樣的傳播出去戚长,然后影響結果盗冷,借用面向對象的一句話,萬物皆是流同廉。

代表:KVO運用

鏈式編程

是將多個操作(多行代碼)通過點號(.)鏈接在一起成為一句代碼,使代碼可讀性好仪糖。a(1).b(2).c(3)

鏈式編程特點:方法的返回值是block,block必須有返回值(本身對象),block參數(shù)(需要操作的值)

代表作 Masonry

4 添加ReactiveCocoa到項目中

使用cocoapods 具體電腦配置cocoapods網(wǎng)上資料一大堆 我就不多說了 自行Google

pod 'ReactiveCocoa', '~> 2.5'

5 分析ReactiveCocoa的中的常見類

仔細看了源碼 發(fā)現(xiàn) RAC中最核心的類是RACSignal迫肖, 好了 接下來就是研究RACSignal了

5-1 RACSignal:信號類

一般表示將來有數(shù)據(jù)傳遞 只要有數(shù)據(jù)改變信號內部接受到數(shù)據(jù) 就會馬上發(fā)出數(shù)據(jù)

注意:
  • RACSignal(信號類) 只是表示數(shù)據(jù)改變時 信號內部會發(fā)出數(shù)據(jù) 它本身不具備發(fā)送信號的能力 而是交給內部一個訂閱者去發(fā)出(下文會講到RACSubject類 有區(qū)別)

  • 默然信號都是冷信號 也就是值改變了也不會觸發(fā) 只有訂閱了這個信號 這個信號才是熱信號 值改變了才會觸發(fā)

  • 訂閱信號:調用信號RACSignal的subscribeNext就能訂閱

RACSignal的簡單使用:
   // 1 創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
      
        // 2 發(fā)送信號
        [subscriber sendNext:@"123"];
        // 如果不發(fā)送數(shù)據(jù) 最好發(fā)送信號完成  內部會自動調用[RACDisposable disposable]取消訂閱信號锅劝。
        [subscriber sendCompleted];
        
        return [RACDisposable disposableWithBlock:^{
            //block調用時刻:當信號發(fā)送完成或者發(fā)送錯誤,就會自動執(zhí)行這個block,取消訂閱信號蟆湖。
            // 執(zhí)行完Block后故爵,當前信號就不在被訂閱了。
            NSLog(@"信號被銷毀了");
        }];
    }];
    
    // 3 訂閱信號
    [signal subscribeNext:^(id x) {
        
//        block 調用時刻 每當有信號發(fā)出數(shù)據(jù) 就會調用block帐姻;
        NSLog(@"接收到數(shù)據(jù)%@",x);
    }];
  • RACSignal的底層實現(xiàn)原理
    • 1.創(chuàng)建信號稠集,首先把didSubscribe保存到信號中奶段,還不會觸發(fā)。
    • 2.當信號被訂閱剥纷,也就是調用signal subscribeNext:nextBlock
    • 2.2 subscribeNext內部會創(chuàng)建訂閱者subscriber痹籍,并且把nextBlock保存到subscriber中。
    • 2.1 subscribeNext內部會調用siganl的didSubscribe
    • 3.siganl的didSubscribe中調用[subscriber sendNext:@1];
    • 3.1 sendNext底層其實就是執(zhí)行subscriber的nextBlock
5-2 RACSubscriber

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

5-3 RACDisposable

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

  • 不想監(jiān)聽某個信號時 可以通過它主動取消訂閱信號
5-4 RACSubject

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

  • 通常用來代替代理 有了它 就不必要定義代理了

RACReplySubject 重復提供信號類 晦鞋,RACSubject的子類

  • RACReplySubject 和RACSubject區(qū)別

  • RACReplySubject 可以先發(fā)送信號再訂閱信號蹲缠, RACSubject就不可以

  • 使用場景1 :如果一個信號每被訂閱一次 就需要把之前的值重復發(fā)送一遍 使用重復提供信號類

  • 使用場景2 :可以設置capacity數(shù)量來限制緩存的value的數(shù)量 即只緩存最新的幾個值

RACSubject 的簡單實用
//    1 創(chuàng)建信號
    RACSubject *subject = [RACSubject subject];    
    // 2 訂閱信號
    [subject subscribeNext:^(id x) {
        NSLog(@"第一個訂閱者 %@",x);
    }];    
    [subject subscribeNext:^(id x) {
        NSLog(@"第二個訂閱者  %@",x);
    }];
    // 3 發(fā)送信號
    [subject sendNext:@123];
    
  • RACSubject的底層實現(xiàn)原理
  • RACSubject底層實現(xiàn) 和RACSignal不一樣
  • 1 調用SubjectNext 訂閱信號 只是把訂閱者保存起來 并且訂閱者的nextBlock已經(jīng)賦值了
  • 2 調用sendNext 發(fā)送信號遍歷剛剛保存的訂閱者 一個一個調用訂閱者的nextBlock
RACReplaySubject 的簡單使用
    // 1 創(chuàng)建信號
    RACReplaySubject *replySubject = [RACReplaySubject subject];
    
    // 2 發(fā)送信號
    [replySubject sendNext:@"我是ReplySubject -- 1"];
    [replySubject sendNext:@"我是ReplySubject -- 2"];    

    // 3 訂閱信號
    [replySubject subscribeNext:^(id x) {        
        NSLog(@"第一個訂閱者接收到的數(shù)據(jù)%@",x);        
    }];
        
    [replySubject subscribeNext:^(id x) {       
        NSLog(@"第二個訂閱者接收到的數(shù)據(jù)%@",x);    
    }];
    
// 下邊是打印結果
第一個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 1
第一個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 2
第二個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 1
第二個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 2
  • RACReplySubject的底層實現(xiàn)原理

    • RACReplaySubject:底層實現(xiàn)和RACSubject不一樣。
    • 1.調用sendNext發(fā)送信號悠垛,把值保存起來线定,然后遍歷剛剛保存的所有訂閱者,一個一個調用訂閱者的nextBlock确买。
    • 2.調用subscribeNext訂閱信號斤讥,遍歷保存的所有值,一個一個調用訂閱者的nextBlock
    • 如果想當一個信號被訂閱湾趾,就重復播放之前所有值芭商,需要先發(fā)送信號,在訂閱信號搀缠。 也就是先保存值铛楣,在訂閱值。
  • RACSubject 的項目中的使用 替換代理
// 在第一個控制器里邊  我用的是脫線跳轉 所有在此方法中獲取控制器  實例化subject  然后訂閱信號
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {    
    DetailViewController *detailVC = segue.destinationViewController;    
    // 實例化
    detailVC.delagateSignal = [RACSubject subject];    
    // 訂閱信號
    [detailVC.delagateSignal subscribeNext:^(id x) {        
        NSLog(@"%@",x);        
    }];
}

//  在DetailViewController.h 中添加屬性

@property(nonatomic, strong)RACSubject *delagateSignal;

// 在DetailViewController.m 中的點擊方法中 判斷 delagateSignal 是否實例話 然后發(fā)送信號
- (IBAction)delegateBtn:(id)sender {    
    if (self.delagateSignal) {
        // 發(fā)送信號
        [self.delagateSignal sendNext:@"我是從詳情里邊出來的哈哈"];
    }
}

5-5 RACTuple:元祖類 類似NSArray 用來包裝值
5-6 RACSequence (Sequence:序列排序) :RAC中的集合類 用于代替NSArray 和 NSDictionary 可以使用它來快速遍歷數(shù)組和字典
  • 簡單使用 遍歷數(shù)組 和遍歷字典
//     1 遍歷數(shù)組
    NSArray *arr = @[@1,@2,@3,@4,@5];
    [arr.rac_sequence.signal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

// 2 遍歷字典

    // 2 遍歷字典
    NSDictionary *dict = @{@"name":@"奧卡姆剃須刀",
                           @"age":@"25",
                           @"location":@"beijing"
                           };    

    [dict.rac_sequence.signal subscribeNext:^(id x) {       
        NSLog(@"%@",x);        
    }];
此處打印出來的鍵值會被包裝為RACTuple元祖類型  以下為打印結果
Reactive Demo[9312:370525] <RACTuple: 0x608000004790> (
    location,
    beijing
)
 
//  所以遍歷字典時候 應該將id直接改為RACTuple

    [dict.rac_sequence.signal subscribeNext:^(RACTuple * x) {        
        // 解包元祖 會把元祖的值 按順序給參數(shù)里邊的變量賦值
        RACTupleUnpack(NSString *key,NSString *value) = x;        

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

    }];
    
// 打印結果 
 name----奧卡姆剃須刀
 age----25
 location----beijing
  • 實現(xiàn)字典轉模型
//     OC寫法
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"PeopleList.plist" ofType:nil];    
    NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];    
    NSMutableArray *modelArr = [NSMutableArray arrayWithCapacity:dictArr.count];    
    for (NSDictionary *dict in dictArr) {        
        PeopleModel *model = [PeopleModel peopleWithDict:dict];
        [modelArr addObject:model];
    }

// RAC 寫法
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"PeopleList.plist" ofType:nil];    
    NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];    
    NSMutableArray *modelArr = [NSMutableArray arrayWithCapacity:dictArr.count];    
// RACSequence 調用subcribeNext 并不會馬上執(zhí)行NextBlock 而是要等一會 可以在下方添加一個nslog  會現(xiàn)在log
    [dictArr.rac_sequence.signal subscribeNext:^(id x) {       
        PeopleModel *model = [PeopleModel peopleWithDict:x];        
        [modelArr addObject:model];
    }];
NSLog(@"奧卡姆剃須刀");



    //  RAC高級寫法    
    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"PeopleList.plist" ofType:nil];    
    NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
    NSArray *modelArr = [[dictArr.rac_sequence map:^id(id value) {        
        return [PeopleModel peopleWithDict:value];        
    }]array];    
    NSLog(@"%@",modelArr);
   
// map: 映射的意思 把原始的值value映射成一個新值 形成一個新的集合 RACDynamicSequence 
// array  把RACDynamicSequence集合準換成我們熟知的數(shù)組
// 底層實現(xiàn) 當信號被訂閱是 會遍歷集合中的原始值  映射成新值 并且保存到新的RACDynamicSequence集合中

5-7 RACCommand :RAC中用于處理事件的類艺普, 可以吧事件如何處理簸州,事件中的數(shù)據(jù)如何傳遞,包裝到這個類中 他可以很方便的監(jiān)控事件的執(zhí)行過程
  • 監(jiān)聽按鈕的點擊歧譬,網(wǎng)絡請求 簡單實用

    // RACCommand使用步驟
    // 1 創(chuàng)建命令
    // 2 在signalBlock中 創(chuàng)建信號signal 作為signalblock的返回
    // 3 執(zhí)行命令 execute


    // 1 創(chuàng)建命令
    RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal *(id input) {
                      
        NSLog(@"執(zhí)行命令%@",input);        

        // 2 創(chuàng)建信號  用來傳遞數(shù)據(jù)
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {        
            // 在這里邊發(fā)送網(wǎng)絡請求 然后將請求道的結果數(shù)據(jù)返回給外界                    
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{                

                [subscriber sendNext:@"我是數(shù)據(jù)"];                
                // 發(fā)送信號完成后 要發(fā)送完成
                [subscriber sendCompleted];
            });                                  
             
            return nil;
        }];
    }];    
    // 3 訂閱RACCommand的信號 在此處可以拿到網(wǎng)絡請求回來的數(shù)據(jù)
    [command.executionSignals subscribeNext:^(id x) {       
        [x subscribeNext:^(id x) {            
            NSLog(@"----%@",x);            
        }];        
    }];
    // RAC 的高級用法
    //switchToLatest  用于signal of signals  獲取 signal of signals 發(fā)出的最新信號也就是可以直接拿到RACCommand中的信號
    [command.executionSignals.switchToLatest subscribeNext:^(id x) {
        
        NSLog(@"switchToLatest---%@",x);
        
    }];
    
    // 4 監(jiān)聽命令是否執(zhí)行完畢  默認會來一次 可以直接跳過 skip表示跳過信號
    [[command.executing skip:1] subscribeNext:^(id x) {
    
        if ([x boolValue] == YES) {
            
            NSLog(@"正在執(zhí)行");
            
        }else{
            
            NSLog(@"執(zhí)行完畢");
        
        }
        
    }];
    
    // 5 執(zhí)行命令 執(zhí)行命令的時候 會調用command的block  訂閱信號時  block中的信號才能發(fā)送出去
    [command execute:@1];
    
  • RACCommand 使用注意

    • 1 signalBlock 必須返回一個信號 不能返回nil 不過可以傳一個空信號 [RACSignal empty];
    • 2 RACCommand 中信號如果數(shù)據(jù)傳遞完 必須調用 [subscriber sendCompleted];這是命令才會執(zhí)行完畢 否則一直在執(zhí)行過程中
    • 3 comman 需要強引用
  • RACCommand的設計思想 signalBlock內部為什么要返回一個信號 這個信號有什么用呢

    • 1 在RAC開發(fā)中 通常會把網(wǎng)絡請求封裝在RACCommand 直接執(zhí)行某個command就能發(fā)送請求
    • 2 在RACCommand內部請求道數(shù)據(jù)的時候 需要把請求的數(shù)據(jù)傳遞給外界這時候就需要signalblock返回的信號傳遞了
  • 如何拿到command中返回信號發(fā)出的數(shù)據(jù)

    • 1 RACCommand 有一個執(zhí)行信號源executionSignals 這個是signal of signals(信號的信號),意思是信號發(fā)出的數(shù)據(jù)是信號慌植,不是普通的類型尸红。
    • 2 訂閱executionSignals 就能拿到RACCommand中返回的信號 然后訂閱signalblock返回的信號 就能獲取發(fā)出的值
  • 監(jiān)聽當前命令是否正在執(zhí)行executing

  • 使用場景 監(jiān)聽按鈕的點擊 網(wǎng)絡請求

5-8 RACMulticastConnection 用于當一個信號被多次訂閱是為了保證創(chuàng)建信號時 避免多次調用創(chuàng)建信號中的block 造成副作用 可以使用這個類創(chuàng)建
  • RACMulticastConnection 通過RACSignal 的publish或者muticast:方法創(chuàng)建
// 來先看一個例子
    // 需求:假設在一個信號中發(fā)送請求巩步,每次訂閱一次都會發(fā)送請求宋距,這樣就會導致多次請求率拒。
    // 解決:使用RACMulticastConnection就能解決.

// 看一下錯誤的例子

    
    // 1 創(chuàng)建請求信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"發(fā)送請求");
        [subscriber sendNext:@1];
        return nil;        
    }];    
    // 2 訂閱信號
    [signal subscribeNext:^(id x) {       
        NSLog(@"接受數(shù)據(jù)1");        
    }];    
    // 3 再次訂閱信號
    [signal subscribeNext:^(id x) {       
        NSLog(@"接收數(shù)據(jù)2");        
    }];    
    // 4 運行結果 會執(zhí)行兩遍發(fā)送請求  也就是每次訂閱都會發(fā)送一次請求
    

// 下邊是使用RACMulticastConnection 能夠解決發(fā)送兩次請求的問題

//    RACMulticastConnection 解決重復請求的問題
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {       
        NSLog(@"發(fā)送請求");
        [subscriber sendNext:@1];        
        return nil;
    }];        
    // 2 創(chuàng)建鏈接
    RACMulticastConnection *connect = [signal publish];    
    // 3 訂閱信號    
    [connect.signal subscribeNext:^(id x) {
        NSLog(@"接受數(shù)據(jù) 1 --%@",x);
    }];    
    [connect.signal subscribeNext:^(id x) {       
        NSLog(@"接受數(shù)據(jù) 2 -- %@",x);        
    }];
    // 4 鏈接 激活信號
    [connect connect];
  • RACMulticastConnection底層原理:

  • 1.創(chuàng)建connect叶撒,connect.sourceSignal -> RACSignal(原始信號) connect.signal -> RACSubject

  • 2.訂閱connect.signal垫毙,會調用RACSubject的subscribeNext河咽,創(chuàng)建訂閱者蛆橡,而且把訂閱者保存起來舌界,不會執(zhí)行block。

  • 3.[connect connect]內部會訂閱RACSignal(原始信號)泰演,并且訂閱者是RACSubject

  • 3.1.訂閱原始信號呻拌,就會調用原始信號中的didSubscribe

  • 3.2 didSubscribe,拿到訂閱者調用sendNext睦焕,其實是調用RACSubject的sendNext

  • 4.RACSubject的sendNext,會遍歷RACSubject所有訂閱者發(fā)送信號藐握。

  • 4.1 因為剛剛第二步靴拱,都是在訂閱RACSubject,因此會拿到第二步所有的訂閱者猾普,調用他們的nextBlock

5-9 RACScheduler :RAC中的隊列 用GCD封裝的
5-10 RACUnit :表示Stream不包含有意義的值 也就是看到這個 可以直接理解為nil

6 ReactiveCocoa 開發(fā)中常見的用法

6-1 代替代理
  • 個人感覺這個方法代替代理并沒有省多少代碼 類似于block 代碼相對集中了而已

 // 代替代理    
// 主控制器中的代碼
    CustomView *V = [[CustomView alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];
    V.backgroundColor = [UIColor redColor];
    [self.view addSubview:V];    
    V.delegate = self;
    
    [[V rac_signalForSelector:@selector(TapClick)] subscribeNext:^(id x) {
        NSLog(@"點擊了視圖中的按鈕%@",x);
    }];
    
// CustomView  中的代碼 和之前遵守協(xié)議設置代理代理實現(xiàn)方法是一樣一樣的
.h

@protocol CustomViewDelagate <NSObject>

- (void)CustomViewTapClick;

@end

@interface CustomView : UIView

@property (nonatomic,weak) id<CustomViewDelagate> delegate;

@end

.m
- (void)TapClick{
    if ([self.delegate respondsToSelector:@selector(CustomViewTapClick)]) {
        [self.delegate CustomViewTapClick];
    }
}

6-2 代替KVO
  • 使用RAC代替KVO很簡單,一句話就可以搞定,而且相比傳統(tǒng)的KVO,不僅代碼不用放在一起寫美觀了很多,同時還能達到高聚合低耦合的目標
//第一種方式   代替KVO
  [RACObserve(scrollView, contentOffset) subscribeNext:^(id x) {
      NSLog(@"%@",x);
  }];

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

6-3 監(jiān)聽事件
  • rac_signalForControlEvents 同樣簡單,一句話搞定
    // 監(jiān)聽事件
    [[self.signalBtn rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(id x) {
        // 傳遞的btn
        NSLog(@"點擊了按鈕%@",x);        
    }];
6-4 代替通知
   // 正確的寫法--1  這個寫法 當dealloc信號發(fā)出的時候 就釋放通知
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {        
        NSLog(@"鍵盤彈出");        
    }];

   // 正確的寫法--2   自己創(chuàng)建一個要釋放的信號
    RACSignal *deallocSignal = [self rac_signalForSelector:@selector(viewWillDisappear:)];    
    [[[[NSNotificationCenter defaultCenter]rac_addObserverForName:UIKeyboardWillShowNotification object:nil] takeUntil:deallocSignal] subscribeNext:^(id x) {
        NSLog(@"鍵盤彈出%@",x);
    }];
    
    // 這是個錯誤的示范  
這個寫法有個問題,這樣子寫信號不會被釋放,當你再次收到鍵盤彈出的通知時他會疊加上次的信號進行執(zhí)行,并一直疊加下去,所以我們在用上面的寫法
  
    [[[NSNotificationCenter defaultCenter]rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {        
        NSLog(@"%@",x);        
    }];

6-5 監(jiān)聽文本框文字的改變
 [self.textFiled.rac_textSignal subscribeNext:^(id x) {       
        NSLog(@"%@",x);
    }];

6-6 處理多個請求 都返回結果的時候統(tǒng)一做處理
- (void)moreRequest{    

    RACSignal *request1 = [RACSignal 
createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {       
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{            
            [subscriber sendNext:@"我是數(shù)據(jù) - 1"];
            [subscriber sendCompleted];
        });        
        return nil;
    }];
    
    RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@"我是數(shù)據(jù) - 2"];
            [subscriber sendCompleted];
        });
        return nil;
    }];
        
    // 前邊的方法參數(shù)和后邊信號的數(shù)據(jù)是一一對應的
    [self rac_liftSelector:@selector(reloadData1:Data2:) withSignalsFromArray:@[request1,request2]];    
}
// 接收到數(shù)據(jù)后在這里統(tǒng)一reloadData
- (void)reloadData1:(id)Data1 Data2:(id)Data2{
    NSLog(@"ReloadData%@---%@",Data1,Data2);
}

6-7 定時器
  • 延時執(zhí)行
    // 延時執(zhí)行
    [[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{       
        NSLog(@"2秒后執(zhí)行我");        
    }];
  • 定時執(zhí)行
    // 定時執(zhí)行  takeUntil 要條件限制一下 否則當控制器銷毀后 還是會繼續(xù)執(zhí)行
    [[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]]takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {
        NSLog(@"每隔1s會執(zhí)行");
    }];
    

7 ReactiveCocoa 開發(fā)中常見的宏

7-1 RAC(TARGET, ...) 用于給某個對象的某個屬性綁定
RAC(self.label,text) = self.textFiled.rac_textSignal;
7-2 RACObserve(TARGET, KEYPATH) 監(jiān)聽某個對象的某個屬性 返回的是信號
    [RACObserve(self.textFiled,center ) subscribeNext:^(id x) {       
        NSLog(@"%@",x);        
    }];
    
7-3 RACTuplePack 把數(shù)據(jù)包裝成RACTuple (元祖類) RACTupleUnpack 把元祖解包成對應的數(shù)據(jù)

    // 把參數(shù)中的數(shù)據(jù)包裝成元祖
    RACTuple *tuple = RACTuplePack(@10,@20,@30);
    
    // 要一一對應付
    RACTupleUnpack(NSString *name,NSString *name2,NSString *name3) = tuple;    
    NSLog(@"%@---%@---%@",name,name2,name3);
                              本文章借鑒網(wǎng)絡多篇文章 僅為學習筆記記錄
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市初家,隨后出現(xiàn)的幾起案子偎窘,更是在濱河造成了極大的恐慌,老刑警劉巖溜在,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陌知,死亡現(xiàn)場離奇詭異,居然都是意外死亡掖肋,警方通過查閱死者的電腦和手機仆葡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來志笼,“玉大人浙芙,你說我怎么就攤上這事∽淹螅” “怎么了嗡呼?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長皇耗。 經(jīng)常有香客問我南窗,道長,這世上最難降的妖魔是什么郎楼? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任万伤,我火速辦了婚禮,結果婚禮上呜袁,老公的妹妹穿的比我還像新娘敌买。我一直安慰自己,他們只是感情好阶界,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布虹钮。 她就那樣靜靜地躺著,像睡著了一般膘融。 火紅的嫁衣襯著肌膚如雪芙粱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天氧映,我揣著相機與錄音春畔,去河邊找鬼。 笑死,一個胖子當著我的面吹牛律姨,可吹牛的內容都是我干的振峻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼择份,長吁一口氣:“原來是場噩夢啊……” “哼铺韧!你這毒婦竟也來了?” 一聲冷哼從身側響起缓淹,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤哈打,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后讯壶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體料仗,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年伏蚊,在試婚紗的時候發(fā)現(xiàn)自己被綠了立轧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡躏吊,死狀恐怖氛改,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情比伏,我是刑警寧澤胜卤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站赁项,受9級特大地震影響葛躏,放射性物質發(fā)生泄漏。R本人自食惡果不足惜悠菜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一舰攒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悔醋,春花似錦摩窃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至德玫,卻和暖如春匪蟀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宰僧。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琴儿。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓段化,卻偏偏與公主長得像,于是被迫代替她去往敵國和親造成。 傳聞我的和親對象是個殘疾皇子显熏,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容