ReactiveCocoa 學習筆記1

一.編程思想

先簡單介紹下目前咱們已知的編程思想。

1.面向過程:處理事情以過程為核心,一步一步的實現。

C語言是面向過程編程的.
面向過程編程主要使用順序、條件選擇、循環三種基本結構來編寫程序。
1.1 順序:按照時間軸順序完成每個處理;
1.2 條件選擇:根據條件的成立與否執行不同的條件分支;
1.3 循環:根據一定的條件反復執行同樣的代碼;

面向過程就是分析出解決問題所需要的步驟,然后用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。
例如:洗衣機的洗衣功能:放水、洗滌、脫水、打干,按照一定的順序執行功能:放水->洗滌->脫水->放水->洗滌->脫水->打干。
在早期計算機配置低、內存小為了節省內存空間,大都采用面向過程編程(以時間換空間)。

2.面向對象:萬物皆對象

滿足面向對象編程的語言,一般會提供類、封裝、繼承、多態等語法和概念來輔助我們進行面向對象編程。
所謂的面向對象就是將我們的程序模塊化、對象化,把具體事物的特性屬性和通過這些屬性來實現一些動作的具體方法封裝到一個類里面,然后創建實例對象,以對象作為程序的基本模塊來進行軟件的分析、設計和開發的一種思考方法。

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

鏈式編程特點:方法的返回值是block,block必須有返回值(本身對象),block參數(需要操作的值)
代表:masonry框架。
例子:
TestView.h

Paste_Image.png

TestView.m

Paste_Image.png

使用方法:


Paste_Image.png

4.響應式編程思想:不需要考慮調用順序,只需要知道考慮結果,類似于蝴蝶效應,產生一個事件,會影響很多東西,這些事件像流一樣的傳播出去,然后影響結果,借用面向對象的一句話,萬物皆是流。
代表:KVO運用。

4.1 響應式編程(FRP Functional Reactive Programming),為解決現代編程問題提供了全新的視角.一旦理解它,可以極大地簡化你的項目,特別是處理嵌套回調的異步事件,復雜的列表過濾和變換,或者時間相關問題。

4.2 響應式編程是一種新的編程風格,其特點是異步或并發、事件驅動、推送PUSH機制以及觀察者模式的衍生。reactive 應用(響應式應用)允許開發人員構建事件驅動(event-driven),可擴展性,彈性的反應系統:提供高度敏感的實時的用戶體驗感覺,可伸縮性和彈性的應用程序棧的支持,隨時可以部署在多核和云計算架構。

二.ReactiveCocoa初見

簡介


ReactiveCocoa簡稱RAC,是一個iOS和OS中的函數式響應式編程框架。
作用


RAC關鍵解決的問題是開發中經常回見的“低聚合,高耦合”問題。在RAC出現之前,我們編寫iOS代碼,大部分都是在響應一些事件:按鈕點擊、接收網絡消息、屬性變化等等。但處理事件的形式在蘋果官方API中卻有好幾種:如target-action、代理方法、KVO、回調或其它。以上這幾種,往往在一個項目中基本都會使用到,在不同的地方會出現很多處理事件的形式,這就帶來了不能很好統一管理問題。因此,我們想,有沒有一個統一管理的解決方案呢?這個方案又是怎樣的呢?到這里ReactiveCocoa就該粉墨登場了,它出現的目的就是為了解決統一標準去管理代碼中的事件。
思想


1.函數式編程(Functional Programming):使用高階函數,例如函數用其他函數作為參數。
2.響應式編程(Reactive Programming):關注于數據流和變化傳播。

所以,你可能聽說過ReactiveCocoa被描述為函數響應式編程(FRP)框架。 以后使用RAC解決問題,就不需要考慮調用順序,直接考慮結果,把每一次操作都寫成一系列嵌套的方法中,使代碼高聚合,方便管理。
原理


1、運用的是Hook(鉤子)思想,Hook是一種用于改變API(應用程序編程接口:方法)執行結果的技術.
2、Hook用處:截獲API調用的技術。
3、Hook原理:在每次調用一個API返回結果之前,先執行你自己的方法,改變結果的輸出。

三.ReactiveCocoa 在objective-c下的簡單使用

目前最新的版本是Swift的 如果想在OC環境下使用只能用 2.5 的版本
Pod 導入
pod 'ReactiveCocoa', '2.5'


1.RACSiganl

RACSiganl:信號類,一般表示將來有數據傳遞,只要有數據改變,信號內部接收到數據,就會馬上發出數據。

信號類(RACSiganl),只是表示當數據改變時,信號內部會發出數據,它本身不具備發送信號的能力,而是交給內部一個訂閱者去發出。

默認一個信號都是冷信號,也就是值改變了,也不會觸發,只有訂閱了這個信號,這個信號才會變為熱信號,值改變了才會觸發。

如何訂閱信號:調用信號RACSignal的subscribeNext就能訂閱。

// RACSignal使用步驟:
    // 1.創建信號 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 3.發送信號 - (void)sendNext:(id)value
        [subscriber sendNext:@"12345"];
        
        // 如果不在發送數據,最好發送信號完成,內部會自動調用[RACDisposable disposable]取消訂閱信號。
        [subscriber sendCompleted];
        
        return [RACDisposable disposableWithBlock:^{
            // block調用時刻:當信號發送完成或者發送錯誤,就會自動執行這個block,取消訂閱信號。
            // 執行完Block后,當前信號就不在被訂閱了。
            NSLog(@"signal 銷毀");
        }];
        
    }];
    
    
    // 2.訂閱信號,才會激活信號. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
    [signal subscribeNext:^(id x) {
        // block調用時刻:每當有信號發出數據,就會調用block.
        NSLog(@"接收到消息->%@", x);
    }];
2.RACSubject

RACSubject:信號提供者,自己可以充當信號,又能發送信號。

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

// RACSubject使用步驟
    // 1.創建信號 [RACSubject subject],跟RACSiganl不一樣,創建信號時沒有block。
    RACSubject *subject = [RACSubject subject];
    
    // 2.訂閱信號 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
    [subject subscribeNext:^(id x) {
        // block調用時刻:當信號發出新值,就會調用.
        NSLog(@"第一個訂閱者%@",x);
    }];
    
    [subject subscribeNext:^(id x) {
        // block調用時刻:當信號發出新值,就會調用.
        NSLog(@"第二個訂閱者%@",x);
    }];
    
    // 3.發送信號 sendNext:(id)value
    [subject sendNext:@"逗比123"];
3.RACReplaySubject

RACReplaySubject:重復提供信號類,RACSubject的子類。

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

使用場景二: 可以設置capacity數量來限制緩存的value的數量,即只緩充最新的幾個值。

// RACReplaySubject使用步驟:
    // 1.創建信號 [RACSubject subject],跟RACSiganl不一樣,創建信號時沒有block。
    RACReplaySubject *replaySubject = [RACReplaySubject subject];
    // 2.可以先訂閱信號,也可以先發送信號。
    //發送信號
    [replaySubject sendNext:@"訂閱之前發送的1"];
    
    // 2.1 訂閱信號 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
    [replaySubject subscribeNext:^(id x) {
        
        NSLog(@"第一個訂閱者接收到的數據%@",x);
    }];

    // 2.2 發送信號 sendNext:(id)value
    [replaySubject sendNext:@"訂閱之后發送的2"];

4.RACTuple RACSequence


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

RACSequence:RAC中的集合類,用于代替NSArray,NSDictionary,可以使用它來快速遍歷數組和字典。

  /**
     RACTuple:元組類,類似NSArray,用來包裝值.
     */
    /**
     RACSequence:RAC中的集合類,用于代替NSArray,NSDictionary,可以使用它來快速遍歷數組和字典。
     */
    
    // 1.遍歷數組
    NSArray *strArr = @[@"1", @"2", @"3", @"4", @"5", @"6",@"1", @"2", @"3", @"4", @"5", @"6"];
    // 這里其實是三步
    // 第一步: 把數組轉換成集合RACSequence numbers.rac_sequence
    // 第二步: 把集合RACSequence轉換RACSignal信號類,numbers.rac_sequence.signal
    // 第三步: 訂閱信號,激活信號,會自動把集合中的所有值,遍歷出來。
    [strArr.rac_sequence.signal subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
        
    }];
    
    // 2.遍歷字典,遍歷出來的鍵值對會包裝成RACTuple(元組對象)
    NSDictionary *dict = @{@"name":@"xmg",@"age":@18};
    [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
        // 解包元組,會把元組的值,按順序給參數里面的變量賦值
        RACTupleUnpack(NSString *key, NSString *value) = x;
        // 相當于以下寫法
        // NSString *key = x[0];
        // NSString *value = x[1];
        NSLog(@"%@ %@",key,value);
    }];
    
    
    // 3.字典轉模型
    NSMutableArray *dictArr = [NSMutableArray array];
    for (int i=0; i<10; i++) {
        [dictArr addObject:@{@"name":[NSString stringWithFormat:@"張%@", @(i)], @"age":@(i)}];
    }

    NSArray *objArr = [[dictArr.rac_sequence.signal map:^id(id value) {
        return [Person personWithDict:value];
    }] toArray];
    
    NSLog(@"->%@", objArr);

5.RACCommand


RAC中用于處理事件的類,可以把事件如何處理,事件中的數據如何傳遞,包裝到這個類中,他可以很方便的監控事件的執行過程。

使用場景:監聽按鈕點擊,網絡請求

 // 1.創建命令 initWithSignalBlock:(RACSignal * (^)(id input))signalBlock
    // 2.在signalBlock中,創建RACSignal,并且作為signalBlock的返回值
    // 3.執行命令 - (RACSignal *)execute:(id)input
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        
        NSLog(@"執行命令");
        
        // 創建空信號,必須返回信號
//        return [RACSignal empty];
        
        // 2.創建信號,用來傳遞數據
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            [subscriber sendNext:@"請求數據789"];
            
            // 注意:數據傳遞完,最好調用sendCompleted,這時命令才執行完畢。
            [subscriber sendCompleted];
            
            return nil;
        }];
    }];
    
    // 強引用命令,不要被銷毀,否則接收不到數據
    _conmmand = command;
    
    // 3.訂閱RACCommand中的信號
    [command.executionSignals subscribeNext:^(id x) {
        
        [x subscribeNext:^(id x) {
            
            NSLog(@"%@",x);
        }];
        
    }];
    
    // RAC高級用法
    // switchToLatest:用于signal of signals,獲取signal of signals發出的最新信號,也就是可以直接拿到RACCommand中的信號
    [command.executionSignals.switchToLatest subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];
    
    // 4.監聽命令是否執行完畢,默認會來一次,可以直接跳過,skip表示跳過第一次信號。
    [[command.executing skip:1] subscribeNext:^(id x) {
        
        if ([x boolValue] == YES) {
            // 正在執行
            NSLog(@"正在執行");
            
        }else{
            // 執行完成
            NSLog(@"執行完成");
        }
        
    }];
    // 5.執行命令
    [_conmmand execute:@1];

6.RACMulticastConnection


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

使用注意:RACMulticastConnection通過RACSignal的-publish或者-muticast:方法創建.

 // 需求:假設在一個信號中發送請求,每次訂閱一次都會發送請求,這樣就會導致多次請求。
     //1.創建請求信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        NSLog(@"發送請求");
        [subscriber sendNext:@"我是測試"];
        return nil;
    }];
    
    //2.訂閱信號
    [signal subscribeNext:^(id x) {
        NSLog(@"接收數據1->%@", x);
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"接收數據2->%@", x);
    }];
    
    // 3.運行結果,會執行兩遍發送請求,也就是每次訂閱都會發送一次請求
// 解決:使用RACMulticastConnection就能解決.
 // RACMulticastConnection:解決重復請求問題
 // 1.創建信號
    RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        NSLog(@"發送請求1");
        [subscriber sendNext:@"haha"];
        
        return nil;
    }];
    
    //2.創建連接
    RACMulticastConnection *multicastConnection = [signal1 publish];
    
    //3.訂閱信號
    // 注意:訂閱信號,也不能激活信號,只是保存訂閱者到數組,必須通過連接,當調用連接,就會一次性調用所有訂閱者的sendNext:
    [multicastConnection.signal subscribeNext:^(id x) {
       
        NSLog(@"訂閱者1 信號->%@", x);
    }];
    
    [multicastConnection.signal subscribeNext:^(id x) {
        NSLog(@"訂閱者2 信號->%@", x);
    }];
    
    //4.連接,激活信號
    [multicastConnection connect];
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容