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

1.ReactiveCocoa開發(fā)中常見用法有哪些?

第1種:代替代理

rac_signalForSelector:用于替代代理

// 1.代替代理,RACSubject
    // RAC方法:可以判斷下某個方法有沒有調(diào)用
    // 只要self調(diào)用Selector就會產(chǎn)生一個信號
    // rac_signalForSelector:監(jiān)聽某個對象調(diào)用某個方法
    [[self rac_signalForSelector:@selector(didReceiveMemoryWarning)] subscribeNext:^(id x) {
        
        NSLog(@"控制器調(diào)用了didReceiveMemoryWarning");
    }];
    // 判斷下redView有沒有調(diào)用btnClick,就表示點擊了按鈕
    [[_redView rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
        NSLog(@"點擊了按鈕");
    }];


第2種:代替KVO

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

 [_redView rac_observeKeyPath:@"name" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
        // 只要監(jiān)聽的屬性一改變調(diào)用
        NSLog(@"%@",_redView.name);
    }];
    
    // KVO:第二種,只要對象的值改變,就會產(chǎn)生信號,訂閱信號
    [[_redView rac_valuesForKeyPath:@"name" observer:nil] subscribeNext:^(id x) {
        
    }];

第3種:監(jiān)聽事件

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

 //  只要按鈕產(chǎn)生這個事件,就會產(chǎn)生一個信號
    [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
        
        NSLog(@"按鈕被點擊%@",x);
    }];
    _btn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        NSLog(@"按鈕點擊");
        return [RACSignal empty];
    }];

第4種:代替通知

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

    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];

第5種:監(jiān)聽文本框文字改變

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

    [_textField.rac_textSignal subscribeNext:^(id x) {
        // x:文本框的文字
        NSLog(@"%@",x);
    }];

第6種:處理當(dāng)界面有多次請求時央勒,需要都獲取到數(shù)據(jù)時不见,才能展示界面

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

  RACSignal *requestHot = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"請求最熱商品");
        [subscriber sendNext:@"獲取最熱商品"];
        return nil;
    }];
    
    RACSignal *requestNew = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"請求最新商品");
//        [subscriber sendNext:@"獲取最新商品"];
        return nil;
    }];
    
    // Selector調(diào)用:當(dāng)所有信號都發(fā)送數(shù)據(jù)的時候調(diào)用
    // 數(shù)組存放信號
    // Selector注意點:參數(shù)根據(jù)數(shù)組元素決定
    // Selector方法參數(shù)類型,就是信號傳遞出來數(shù)據(jù)
    [self rac_liftSelector:@selector(updateUI:data2:) withSignalsFromArray:@[requestHot,requestNew]];
    
}
// 只要兩個請求都請求完成的時候才會調(diào)用
- (void)updateUI:(NSString *)data1 data2:(NSString *)data2
{
    NSLog(@"%@ %@",data1,data2);
}

2.ReactiveCocoa常見宏

第一種

RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于給某個對象的某個屬性綁定


    // 給某個對象的某個屬性綁定一個信號,只要產(chǎn)生信號,就會把信號的內(nèi)容給對象的屬性賦值
    // 給label的text屬性綁定一個信號
    RAC(_label,text) = _texfField.rac_textSignal;

第二種

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

    // 觀察某個對象某個屬性
    [RACObserve(self, name) subscribeNext:^(id x) {
       
        NSLog(@"%@",x);
    }];

第三種

@weakify(Obj)和@strongify(Obj),一般兩個都是配套使用,解決循環(huán)引用問題

第四種

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

    // RACTuplePack:快速把一些數(shù)據(jù)包裝成元組類
    RACTuple *tuple = RACTuplePack(@"123",@1);

第五種

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

    // 參數(shù):需要解析生成出來變量名
    RACTupleUnpack(NSString *str,NSNumber *num) = tuple;
    
    NSLog(@"%@ %@",str,num);

3.ReactiveCocoa常見操作方法

  • ReactiveCocoa操作原理
    所有的信號(RACSignal)都可以進行操作處理稳吮,因為所有操作方法都定義在RACStream.h中,因此只要繼承RACStream就有了操作處理方法

  • ReactiveCocoa操作思想
    運用的是Hook(鉤子)思想井濒,Hook是一種用于改變API(應(yīng)用程序編程接口:方法)執(zhí)行結(jié)果的技術(shù). Hook用處:截獲API調(diào)用的技術(shù)灶似。 Hook原理:在每次調(diào)用一個API返回結(jié)果之前,先執(zhí)行你自己的方法瑞你,改變結(jié)果的輸出

  • ReactiveCocoa核心方法bind
    ReactiveCocoa操作的核心方法是bind(綁定),而且RAC中核心開發(fā)方式酪惭,也是綁定,之前的開發(fā)方式是賦值者甲,而用RAC開發(fā)春感,應(yīng)該把重心放在綁定,也就是可以在創(chuàng)建一個對象的時候虏缸,就綁定好以后想要做的事情鲫懒,而不是等賦值之后在去做事情

核心方法bind的使用

  RACSignal *bindSignal = [_textField.rac_textSignal bind:^RACStreamBindBlock{
        // block調(diào)用時刻:只要一個信號被綁定就會調(diào)用.表示信號綁定完成
        
        NSLog(@"源信號被綁定");
        return ^RACStream *(id value, BOOL *stop){
            // RACStreamBindBlock什么時候調(diào)用:每次源信號發(fā)出內(nèi)容,就會調(diào)用這個block
            
            // value:源信號發(fā)出的內(nèi)容
            NSLog(@"源信號發(fā)出的內(nèi)容:%@",value);
            
            // RACStreamBindBlock作用:在這個block處理源信號的內(nèi)容
            value = [NSString stringWithFormat:@"xmg%@",value];
            // block返回值:信號(把處理完的值包裝成一個信號,返回出去)
            
            // 創(chuàng)建一個信號,并且這個信號的傳遞的值是我們處理完的值,value
            return [RACReturnSignal return:value];
        };
        
    }];
    
    // 訂閱綁定信號,不在是源信號
    [bindSignal subscribeNext:^(id x) {
       
        NSLog(@"%@",x);
    }];
    

    // 執(zhí)行流程
    /*
        1.文字改變源信號
        2.綁定源信號,[_textField.rac_textSignal bind]
        * 調(diào)用bind返回綁定好的信號,didSubscribe
        3.訂閱綁定信號
            * 創(chuàng)建訂閱者
            * 調(diào)用綁定信號的didSubscribe
        4.執(zhí)行綁定信號didSubscribe
        5.執(zhí)行bind方法傳入的block
        6.訂閱源信號
        7.只要源信號一發(fā)出內(nèi)容,就會調(diào)用id signal = bindingBlock(x, &stop);
            * signal:把值處理完的信號
        
     */

ReactiveCocoa操作方法之映射(flattenMap,Map)

flattenMap:信號中信號,signalOfSignals

[[_textField.rac_textSignal flattenMap:^RACStream *(id value) {
        // value:源信號的內(nèi)容
        value = [NSString stringWithFormat:@"xmg%@",value];
        // 返回值:信號,把處理完的值包裝成信號返回出去
        return [RACReturnSignal return:value];
    }] subscribeNext:^(id x) {
        // 訂閱[RACReturnSignal return:value發(fā)送值
        
        // x:綁定信號的值
        NSLog(@"%@",x);
    }];

map: 用于普通信號,信號發(fā)出普通值

  [[_textField.rac_textSignal map:^id(id value) {
        // value:源信號的內(nèi)容
        // 返回值,就是處理源信號的內(nèi)容,直接返回
        return [NSString stringWithFormat:@"----xmg%@",value];
        
    }] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

FlatternMap和Map的區(qū)別

  • 1.FlatternMap中的Block返回信號。
  • 2.Map中的Block返回對象刽辙。
  • 3.開發(fā)中窥岩,如果信號發(fā)出的值不是信號,映射一般使用Map
  • 4.開發(fā)中宰缤,如果信號發(fā)出的值是信號颂翼,映射一般使用FlatternMap晃洒。

ReactiveCocoa操作方法之組合

concat:按一定順序拼接信號,當(dāng)多個信號發(fā)出的時候疚鲤,有順序的接收信號

 // concat:連接信號,有順序的拼接,一定要等第一個信號完成的時候,第二個信號才會被激活
    RACSubject *signalA = [RACSubject subject];
    RACSubject *signalB = [RACSubject subject];
    
    // 組合信號
    RACSignal *signals = [signalA concat:signalB];
    
    // 訂閱組合信號
    [signals subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];
    
    // 發(fā)送數(shù)據(jù)
    [signalA sendNext:@1];
    [signalA sendCompleted];
    [signalB sendNext:@2];

then:用于連接兩個信號锥累,當(dāng)?shù)谝粋€信號完成,才會連接then返回的信號

 RACSubject *signalA = [RACSubject subject];
    RACSubject *signalB = [RACSubject subject];
    
    // 組合
    RACSignal *signals = [signalA then:^RACSignal *{
        return signalB;
    }];
    
    [signals subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    
    [signalA sendNext:@1];
    [signalA sendCompleted];
    [signalB sendNext:@2];
 then跟concat區(qū)別:監(jiān)聽不到第一個信號的值,共同點都是必須第一個信號完成,第二個信號才會激活

merge: 把多個信號合并為一個信號集歇,任何一個信號有新值的時候就會調(diào)用

// merge:合并,任何一個信號只要發(fā)送值,就能訂閱
    RACSubject *signalA = [RACSubject subject];
    RACSubject *signalB = [RACSubject subject];
    
    RACSignal *signals = [signalA merge:signalB];
    
    [signals subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    
    [signalA sendNext:@1];
    
    [signalB sendNext:@2];
    
    [signalB sendNext:@3];

zipWith:把兩個信號壓縮成一個信號桶略,只有當(dāng)兩個信號同時發(fā)出信號內(nèi)容時,并且把兩個信號的內(nèi)容合并成一個元組诲宇,才會觸發(fā)壓縮流的next事件

RACSubject *signalA = [RACSubject subject];
    RACSubject *signalB = [RACSubject subject];
    
    RACSignal *signals = [signalA zipWith:signalB];
    
    [signals subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];
    
    // zipWith:當(dāng)兩個信號都發(fā)出內(nèi)容的時候,才能被訂閱到
    [signalA sendNext:@1];
    [signalB sendNext:@2];
    
    [signalB sendNext:@3];
    [signalA sendNext:@4];

combineLatest:將多個信號合并起來际歼,并且拿到各個信號的最新的值,必須每個合并的signal至少都有過一次sendNext,才會觸發(fā)合并的信號

  // 第一個參數(shù):就是存放需要合并信號
    [[RACSignal combineLatest:@[_textField1.rac_textSignal,_textField2.rac_textSignal] reduce:^id(NSString *str1,NSString *str2){
        NSLog(@"%@ ---- %@",str1,str2);
        // block:只要任意一個信號發(fā)出內(nèi)容,就會調(diào)用
        // block參數(shù)個數(shù):由信號決定
        // block參數(shù)類型:block的參數(shù)就是信號發(fā)出值
        // 把兩個信號中的值聚合成哪個值
        return @(str1.length && str2.length);
    }] subscribeNext:^(id x) {
        _btn.enabled = [x boolValue];
        NSLog(@"%@",x);
    }];

reduce聚合:用于信號發(fā)出的內(nèi)容是元組姑蓝,把信號發(fā)出元組的值聚合成一個值

    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;
    }];

    // 聚合
    // 常見的用法鹅心,(先組合在聚合)。combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock
    // reduce中的block簡介:
    // reduceblcok中的參數(shù)纺荧,有多少信號組合旭愧,reduceblcok就有多少參數(shù),每個參數(shù)就是之前信號發(fā)出的內(nèi)容
    // reduceblcok的返回值:聚合信號之后的內(nèi)容宙暇。
  RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber *num1 ,NSNumber *num2){

       return [NSString stringWithFormat:@"%@ %@",num1,num2];

   }];

    [reduceSignal subscribeNext:^(id x) {

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

ReactiveCocoa操作方法之過濾

  • filter:過濾信號输枯,使用它可以獲取滿足條件的信號
  • ignore:忽略完某些值的信號
  • distinctUntilChanged:當(dāng)上一次的值和當(dāng)前的值有明顯的變化就會發(fā)出信號,否則會被忽略掉
  • take:從開始一共取N次的信號
  • takeLast:取最后N次的信號,前提條件占贫,訂閱者必須調(diào)用完成桃熄,因為只有完成,就知道總共有多少信號
  • takeUntil:(RACSignal *):獲取信號直到執(zhí)行完這個信號
  • skip:(NSUInteger):跳過幾個信號,不接受
  • switchToLatest:用于signalOfSignals(信號的信號)型奥,有時候信號也會發(fā)出信號瞳收,會在signalOfSignals中,獲取signalOfSignals發(fā)送的最新信號

ReactiveCocoa操作方法之秩序

  • doNext: 執(zhí)行Next之前厢汹,會先執(zhí)行這個Block
  • doCompleted: 執(zhí)行sendCompleted之前螟深,會先執(zhí)行這個Block

ReactiveCocoa操作方法之線程

  • deliverOn: 內(nèi)容傳遞切換到制定線程中,副作用在原來線程中,把在創(chuàng)建信號時block中的代碼稱之為副作用
  • subscribeOn: 內(nèi)容傳遞和副作用都會切換到制定線程中

ReactiveCocoa操作方法之時間

  • timeout:超時烫葬,可以讓一個信號在一定的時間后,自動報錯
  • interval 定時:每隔一段時間發(fā)出信號
  • delay: 延遲發(fā)送next

ReactiveCocoa操作方法之重復(fù)

  • retry重試 :只要失敗厘灼,就會重新執(zhí)行創(chuàng)建信號中的block,直到成功
  • replay重放:當(dāng)一個信號被多次訂閱,反復(fù)播放內(nèi)容
  • throttle節(jié)流:當(dāng)某個信號發(fā)送比較頻繁時夹纫,可以使用節(jié)流咽瓷,在某一段時間不發(fā)送信號內(nèi)容设凹,過了一段時間獲取信號的最新內(nèi)容發(fā)出

4.學(xué)習(xí)MVVM架構(gòu)思想

  • (1)程序為什么要架構(gòu)?
    便于程序員開發(fā)和維護代碼

  • (2)常見的架構(gòu)思想有哪些茅姜?

    • MVC ---- M:模型 V:視圖 C:控制器)
    • MVVM ----M:模型 V:視圖+控制器 VM:視圖模型
    • MVCS ---- M:模型 V:視圖 C:控制器 S:服務(wù)類
    • VIPER ---- V:視圖 I:交互器 P:展示器 E:實體 R:路由
  • (3)MVVM思想
    • 模型(M):保存視圖數(shù)據(jù)
    • 視圖+控制器(V):展示內(nèi)容 + 如何展示
    • 視圖模型(VM):處理展示的業(yè)務(wù)邏輯闪朱,包括按鈕的點擊月匣,數(shù)據(jù)的請求和解析
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奋姿,隨后出現(xiàn)的幾起案子锄开,更是在濱河造成了極大的恐慌,老刑警劉巖称诗,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍悴,死亡現(xiàn)場離奇詭異,居然都是意外死亡寓免,警方通過查閱死者的電腦和手機癣诱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袜香,“玉大人撕予,你說我怎么就攤上這事◎谑祝” “怎么了实抡?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長欢策。 經(jīng)常有香客問我吆寨,道長,這世上最難降的妖魔是什么猬腰? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任鸟废,我火速辦了婚禮,結(jié)果婚禮上姑荷,老公的妹妹穿的比我還像新娘盒延。我一直安慰自己,他們只是感情好鼠冕,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布添寺。 她就那樣靜靜地躺著,像睡著了一般懈费。 火紅的嫁衣襯著肌膚如雪计露。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天憎乙,我揣著相機與錄音票罐,去河邊找鬼。 笑死泞边,一個胖子當(dāng)著我的面吹牛该押,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阵谚,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蚕礼,長吁一口氣:“原來是場噩夢啊……” “哼烟具!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起奠蹬,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤朝聋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后囤躁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冀痕,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年狸演,在試婚紗的時候發(fā)現(xiàn)自己被綠了金度。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡严沥,死狀恐怖猜极,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情消玄,我是刑警寧澤跟伏,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站翩瓜,受9級特大地震影響受扳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兔跌,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一勘高、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坟桅,春花似錦华望、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至夸楣,卻和暖如春宾抓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豫喧。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工石洗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人紧显。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓讲衫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸟妙。 傳聞我的和親對象是個殘疾皇子焦人,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

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