ReactiveCocoa學(xué)習(xí)篇——【上】

1.ReactiveCocoa是什么阱当?
ReactiveCocoa(簡稱為RAC),是由Github開源的一個應(yīng)用于iOS和OS開發(fā)的新框架,Cocoa是蘋果整套框架的簡稱药版,因此很多蘋果框架喜歡以Cocoa結(jié)尾。
關(guān)鍵詞:ReactiveCocoa是Github開源的一個框架

2.ReactiveCocoa有什么用炼邀?
在iOS開發(fā)過程中陆错,經(jīng)常會響應(yīng)某些事件來處理某些業(yè)務(wù)邏輯灯抛,例如按鈕的點擊,上下拉刷新音瓷,網(wǎng)絡(luò)請求对嚼,屬性的變化(通過KVO)或者用戶位置的變化(通過CoreLocation)。但是這些事件都用不同的方式來處理绳慎,比如action纵竖、delegate、KVO杏愤、callback等靡砌。

其實這些事件,都可以通過RAC處理声邦,ReactiveCocoa為事件提供了很多處理方法乏奥,而且利用RAC處理事件很方便,可以把要處理的事情亥曹,和監(jiān)聽的事情的代碼放在一起邓了,這樣非常方便我們管理,就不需要跳到對應(yīng)的方法里媳瞪。非常符合我們開發(fā)中高聚合骗炉,低耦合的思想。
關(guān)鍵詞:在iOS日常開發(fā)過程中使用的一些處理事件的方法蛇受,RAC也能處理并且更方便

3.已知的編程思想都有哪些句葵?

  • 面向過程
    • 處理事情以過程為核心,一步一步的實現(xiàn)。
  • 面向?qū)ο?
    • 萬物皆對象
  • 鏈?zhǔn)骄幊趟枷?
    • 是將多個操作(多行代碼)通過點號(.)鏈接在一起成為一句代碼,使代碼可讀性好乍丈。
  • 響應(yīng)式編程思想
    • 不需要考慮調(diào)用順序剂碴,只需要知道考慮結(jié)果,類似于蝴蝶效應(yīng)轻专,產(chǎn)生一個事件忆矛,會影響很多東西,這些事件像流一樣的傳播出去请垛,然后影響結(jié)果催训,借用面向?qū)ο蟮囊痪湓挘f物皆是流宗收。
  • 函數(shù)式編程思想
    • 是把操作盡量寫成一系列嵌套的函數(shù)或者方法調(diào)用漫拭。
  • 函數(shù)響應(yīng)式編程(FRP)
    • 不需要考慮調(diào)用順序,直接考慮結(jié)果混稽,把每一次操作都寫成一系列嵌套的方法中采驻,使代碼高聚合,方便管理荚坞。

4.如何導(dǎo)入ReactiveCocoa框架挑宠?

  • 這里使用CocoaPods來導(dǎo)入
  • 創(chuàng)建一個新的工程演示下框架的導(dǎo)入
  • 打開終端,進(jìn)入工程文件的同級目錄
  • 新建一個profile文件颓影,輸入一下內(nèi)容并保存
use_frameworks!
pod 'ReactiveCocoa', '~> 4.0.2-alpha-1'
  • 在終端輸入指令pod install完成安裝

5.ReactiveCocoa常見類有哪些?

第1種: RACSignal 信號類

操作步驟:

  • 創(chuàng)建信號(冷信號)
  • 訂閱信號(熱信號)
  • 發(fā)送數(shù)據(jù)
    // 1.創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    // block什么時候調(diào)用:當(dāng)信號被訂閱的時候就會調(diào)用
    // block作用:在這里面?zhèn)鬟f數(shù)據(jù)出去
        
        // 3.發(fā)送數(shù)據(jù)
        [subscriber sendNext:@1]; 
        return nil;
    }];
    
    // 2.訂閱信號
    // x:信號傳遞出來的數(shù)據(jù)
    [signal subscribeNext:^(id x) {
    // block什么時候調(diào)用:當(dāng)信號內(nèi)部,發(fā)送數(shù)據(jù)的時候,就會調(diào)用,并且會把值傳遞給你
    // block作用:在這個block中處理數(shù)據(jù)
        
        NSLog(@"%@",x);
    }];

RACSignal:表示有數(shù)據(jù)傳遞的時候
RACDisposable:取消訂閱信號
RACSubscriber:訂閱者,發(fā)送數(shù)據(jù)

/*
執(zhí)行流程:
1.創(chuàng)建信號RACDynamicSignal
 * 1.1 把didSubscribe保存到RACDynamicSignal
2.訂閱信號
 *  2.1 創(chuàng)建訂閱者,把nextBlock保存到訂閱者里面去
 *  2.2 就會調(diào)用信號的didSubscribe
3.執(zhí)行didSubscribe
 *  3.1 拿到訂閱者發(fā)送訂閱者
 * [subscriber sendNext:@1]內(nèi)部就是拿到訂閱者的nextBlock
 * 信號被訂閱,就會執(zhí)行創(chuàng)建信號時didSubscribe
 * 訂閱者發(fā)送信號,就是調(diào)用nextBlock
 */

第2種: RACDisposable 取消訂閱或者清理資源

操作步驟:

  • 創(chuàng)建信號
  • 訂閱信號
  • 發(fā)送信號
    // 只要訂閱者一直在,表示需要一直訂閱信號,信號不會自動被取消訂閱
    // 1.創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        _subscriber = subscriber;
        
        // 3.發(fā)送信號
        [subscriber sendNext:@1];
        
        return [RACDisposable disposableWithBlock:^{
       // 當(dāng)信號取消訂閱的時候就會調(diào)用
            NSLog(@"信號被取消訂閱");
        }];
    }];

    // 2.訂閱信號
    RACDisposable *disposable = [signal subscribeNext:^(id x) {
       
        NSLog(@"%@",x);
        
    }];
    
    
    // 取消訂閱(主動取消)
    [disposable dispose];
    
}

第3種:RACSubject 信號提供者

信號提供者:既可以充當(dāng)信號,也可以充當(dāng)訂閱者,發(fā)送數(shù)據(jù) 一個信號允許被多次訂閱

操作步驟:

  • 創(chuàng)建信號
  • 訂閱信號
  • 發(fā)送信號

    // 1.創(chuàng)建信號
    RACSubject *subject = [RACSubject subject];
    
    // 2.訂閱信號
    [subject subscribeNext:^(id x) {
        
        NSLog(@"訂閱者一%@",x);
    }];
    
    [subject subscribeNext:^(id x) {
        
        NSLog(@"訂閱者二%@",x);
    }];
    
    
    // 3.發(fā)送信號
    [subject sendNext:@1];


/*
 執(zhí)行流程:
 1.創(chuàng)建信號
 2.訂閱信號
 * 創(chuàng)建訂閱者
 * [self subscribe:o]訂閱信號,僅僅是把訂閱者保存起來.
 3.發(fā)送信號
 * 把所有的訂閱者遍歷出來,一個一個的調(diào)用它們nextBlock
 */

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

允許先發(fā)送信號,在訂閱信號 重復(fù)信號提供者

操作步驟:

  • 創(chuàng)建信號
  • 訂閱信號
  • 發(fā)送信號
    // 1.創(chuàng)建信號
    RACReplaySubject *subject = [RACReplaySubject subject];
    
    // 2.發(fā)送信號
    [subject sendNext:@"123123"];
    [subject sendNext:@"345"];
    [subject sendNext:@"456456"];
    // 1.把值保存到數(shù)組
    // 2.遍歷所有的訂閱者,調(diào)用nextBlock
    
    // 3.訂閱信號
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者一%@",x);
    }];
    // 1.遍歷所有值,拿到訂閱者去發(fā)送
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者二%@",x);
    }];
    
/*
 執(zhí)行流程:
 1.創(chuàng)建信號
 2.訂閱信號
 * 創(chuàng)建訂閱者,保存nextBlock保存
 * 遍歷valuesReceived需要發(fā)送的所有值,拿到一個一個值,利用訂閱者發(fā)送數(shù)據(jù)
 3.發(fā)送信號
 * 把發(fā)送的值,保存到數(shù)組
 * 把所有的訂閱者遍歷出來,一個一個的調(diào)用它們nextBlock
 */

第5種:RACMulticastConnection

用于當(dāng)一個信號懒鉴,被多次訂閱時诡挂,為了保證創(chuàng)建信號時,避免多次調(diào)用創(chuàng)建信號中的block临谱,造成副作用璃俗,可以使用這個類處理

簡單使用

 // 1.創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        NSLog(@"發(fā)送請求");
        
        // 3.發(fā)送信號
        [subscriber sendNext:@"網(wǎng)絡(luò)數(shù)據(jù)"];
        
        return nil;
    }];
    
    // 2.把信號轉(zhuǎn)換成連接類
    RACMulticastConnection *connect = [signal publish];
    
    // 3.訂閱連接類的信號,注意:一定是訂閱連接類的信號,不再是源信號
    [connect.signal subscribeNext:^(id x) {
       
        NSLog(@"%@",x);
        
    }];
    
    [connect.signal subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
        
    }];
    [connect.signal subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
        
    }];
    
    // 4.連接
    [connect connect];

一個信號即使被訂閱多次,也只是發(fā)送一次請求 RACMulticastConnection:用于信號中請求數(shù)據(jù),避免多次請求數(shù)據(jù)

   /* 
     執(zhí)行流程
        1.創(chuàng)建信號
        * 創(chuàng)建RACDynamicSignal,并且把didSubscribe保存到
        2.把信號轉(zhuǎn)換成連接類
        * 創(chuàng)建信號提供者RACSubject
        * [self multicast:subject]:設(shè)置原始信號的多點傳播subject,本質(zhì)就是把subject設(shè)置為原始信號的訂閱者
        * 創(chuàng)建RACMulticastConnection,把原始信號保存到_sourceSignal,把subject保存到_signal
        3.保存訂閱者
        4.連接 [connect connect]
        * 訂閱_sourceSignal,并且設(shè)置訂閱者為subject
        5.執(zhí)行didSubscribe
        6.[subject sendNext]遍歷所有的訂閱者發(fā)送信號
     */

第6種:RACCommand 用于處理事件的類

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

  • 使用場景: 監(jiān)聽按鈕點擊,網(wǎng)絡(luò)請求
  • RACCommand使用步驟:創(chuàng)建命令 -> 執(zhí)行命令
  • RACCommand使用注意點:內(nèi)部不允許傳入一個nil的信號
// 1.創(chuàng)建命令
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        // signalBlock調(diào)用時刻:只要命令一執(zhí)行就會調(diào)用
        // signalBlock作用:處理事件
        NSLog(@"%@",input);
        
        
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
                NSLog(@"didSubscribe");
            // didSubscribe調(diào)用時刻:執(zhí)行命令過程中,就會調(diào)用
            // didSubscribe作用:傳遞數(shù)據(jù)
            
            // subscriber -> [RACReplaySubject subject]
            // RACReplaySubject:把值保存起來,遍歷所有的訂閱者發(fā)送這個值
            [subscriber sendNext:@1];
            
            return nil;
        }];
    }];
    
    // 2.執(zhí)行命令
    RACReplaySubject *replaySubject = (RACReplaySubject *)[command execute:@"執(zhí)行命令"];
    
    
    // 3.獲取命令中產(chǎn)生的數(shù)據(jù),訂閱信號
    [replaySubject subscribeNext:^(id x) {
       
        NSLog(@"%@",x);
    }];
    // 1.創(chuàng)建訂閱者,訂閱信號
    // 2.遍歷所有值,拿到訂閱者去發(fā)送
    /* 
     執(zhí)行流程:
    // 1.創(chuàng)建命令
        * 把signalBlock保存到命令中
     // 2.執(zhí)行命令
        * 調(diào)用命令signalBlock
        * 創(chuàng)建多點傳播連接類, 訂閱源信號,并且設(shè)置源信號的訂閱者為RACReplaySubject
        * 返回源信號的訂閱者
    */

switchToLatest用法

 // 1.創(chuàng)建了一個信號中的信號,只能發(fā)送信號
    RACSubject *signalOfSignals = [RACSubject subject];
    
    // 創(chuàng)建信號,發(fā)送普通數(shù)據(jù)
    RACSubject *signalA = [RACSubject subject];
    RACSubject *signalB = [RACSubject subject];
    
    // 2.通過訂閱信號中信號,拿到signal發(fā)出值
    // 獲取信號中的信號發(fā)送最新信號
    [signalOfSignals.switchToLatest subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];
    
    
    // 3.發(fā)送信號
    // 信號中的信號發(fā)送數(shù)據(jù)
    [signalOfSignals sendNext:signalA];
    [signalOfSignals sendNext:signalB];
    
    // 信號發(fā)送數(shù)據(jù)
    [signalB sendNext:@"發(fā)送普通數(shù)據(jù)"];

  // 1.創(chuàng)建命令
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        // 1.命令執(zhí)行的時候調(diào)用
        NSLog(@"執(zhí)行SignalBlock");
        // 處理事情,網(wǎng)絡(luò)請求
        
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            // 2.執(zhí)行完SignalBlock,接著就會調(diào)用
            NSLog(@"執(zhí)行didSubscribe");
            // 傳送數(shù)據(jù),也只會來一次
            [subscriber sendNext:@"請求到網(wǎng)絡(luò)數(shù)據(jù)"];
            
            // 一定要做事情,聲明數(shù)據(jù)傳遞完成
            // 當(dāng)數(shù)據(jù)傳遞完成,命令就執(zhí)行完成
            [subscriber sendCompleted];
            
            return nil;
        }];
    }];

    // 直接獲取命令中新發(fā)出信號
    // switchToLatest:只能用于signalOfSignals
    // 作用:就是拿到signalOfSignals發(fā)出的最新信號
    [command.executionSignals.switchToLatest subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];
    
    // 訂閱當(dāng)前命令執(zhí)行狀態(tài)的信號,正在執(zhí)行,沒有執(zhí)行
    [command.executing subscribeNext:^(id x) {
        // x:YES 正在執(zhí)行
        // x:No 沒有執(zhí)行/執(zhí)行完成
        if ([x boolValue] == YES) {
            NSLog(@"正在執(zhí)行");
        }else{
            NSLog(@"沒有執(zhí)行/執(zhí)行完成");
        }
        
    }];
    
    // 2.執(zhí)行命令
    RACSignal *signal = [command execute:@1];

6.ReactiveCocoa常用集合類抄课?

RACTuple 和RACSequence 的使用

RACTuple: 元組類,類似NSArray,用來包裝值. RACSequence: RAC中的集合類唱星,用于代替NSArray,NSDictionary,可以使用它來快速遍歷數(shù)組和字典

簡單使用

    RACTuple *tuple = [RACTuple tupleWithObjectsFromArray:@[@"1",@1,@3,@5]];
    NSString *str = tuple[0];

OC->RAC

    NSArray *arr = @[@"123",@1,@3,@5];
    
    // OC數(shù)組轉(zhuǎn)換成RAC集合
    RACSequence *sequence = arr.rac_sequence;
    
    // 把集合轉(zhuǎn)換成signal
    RACSignal *signal = sequence.signal;
    
    // 訂閱集合類的信號,只要訂閱這個信號,就會遍歷集合中所有元素
    [signal subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];
    
    [arr.rac_sequence.signal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

宏的使用

    NSDictionary *dict = @{@"name":@"xmg",@"age":@18};
    
    [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
        //        id value = x[1];
        //        id key = x[0];
        
        // 宏的參數(shù),存放需要生成的變量名
        // 宏會自動生成參數(shù)里面的變量
        RACTupleUnpack(id key,id value) = x;
        
        NSLog(@"%@ : %@",key,value);
    }];

字典轉(zhuǎn)模型
方式一:

    // RAC:集合,相當(dāng)于數(shù)組或者字典
    // 這個類的創(chuàng)建必須要依賴于數(shù)組或者字典
    // 解析plist
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
    NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
    _flags = [NSMutableArray array];
    
    [dictArr.rac_sequence.signal subscribeNext:^(NSDictionary *x) {
        Flag *flag =  [Flag flagWithDict:x];
        [_flags addObject:flag];
    }];

方式二:

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
    NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
    _flags = [NSMutableArray array];

   _flags = [[dictArr.rac_sequence map:^id(id value) {
        // value:就是原始信號發(fā)送的值,字典
        // block返回值就是需要映射的對象
        return [Flag flagWithDict:value];
    }] array];
    NSLog(@"%@",_flags);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市跟磨,隨后出現(xiàn)的幾起案子间聊,更是在濱河造成了極大的恐慌,老刑警劉巖抵拘,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哎榴,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機尚蝌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門迎变,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人飘言,你說我怎么就攤上這事衣形。” “怎么了热凹?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵泵喘,是天一觀的道長。 經(jīng)常有香客問我般妙,道長纪铺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任碟渺,我火速辦了婚禮鲜锚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘苫拍。我一直安慰自己芜繁,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布绒极。 她就那樣靜靜地躺著骏令,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垄提。 梳的紋絲不亂的頭發(fā)上榔袋,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音铡俐,去河邊找鬼凰兑。 笑死,一個胖子當(dāng)著我的面吹牛审丘,可吹牛的內(nèi)容都是我干的吏够。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滩报,長吁一口氣:“原來是場噩夢啊……” “哼锅知!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起露泊,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤喉镰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惭笑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侣姆,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡生真,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了捺宗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柱蟀。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蚜厉,靈堂內(nèi)的尸體忽然破棺而出长已,到底是詐尸還是另有隱情,我是刑警寧澤昼牛,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布术瓮,位于F島的核電站,受9級特大地震影響贰健,放射性物質(zhì)發(fā)生泄漏胞四。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一伶椿、第九天 我趴在偏房一處隱蔽的房頂上張望辜伟。 院中可真熱鬧,春花似錦脊另、人聲如沸导狡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旱捧。三九已至,卻和暖如春踩麦,著一層夾襖步出監(jiān)牢的瞬間廊佩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工靖榕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人顽铸。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓茁计,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谓松。 傳聞我的和親對象是個殘疾皇子星压,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355

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