RAC_6.終結(jié)篇

6 RAC終結(jié)篇

6.1 映射

RAC的映射主要有兩個(gè)方法(flattenMap map),這兩個(gè)方法主要用于將信號(hào)源的內(nèi)容映射成為一個(gè)新的信號(hào)。

  • flattenMap
    它其實(shí)也是綁定信號(hào),一般用于信號(hào)中的信號(hào)。
    RACSubject *subject = [RACSubject subject];
   
   RACSignal *signal = [subject flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
       value = [NSString stringWithFormat:@"處理數(shù)據(jù):%@",value];
       //返回信號(hào)用來(lái)包裝修改過(guò)的內(nèi)容
       return [RACReturnSignal return:value];
   }];
   
   //訂閱綁定信號(hào)
   [signal subscribeNext:^(id  _Nullable x) {
       NSLog(@"%@",x);
   }];
   
   //發(fā)送數(shù)據(jù)
   [subject sendNext:@"123"];

運(yùn)行如圖:

image

看起來(lái)有點(diǎn)繞,說(shuō)白了我們?cè)谑裁磮?chǎng)景下會(huì)用到這種呢?

就在我們發(fā)送的數(shù)據(jù),需要對(duì)數(shù)據(jù)進(jìn)行處理然后再訂閱這個(gè)信號(hào)的時(shí)候就可以使用這種方式,其實(shí)跟我們上一節(jié)中提到的bind是一樣的。

  • map

這個(gè)方法跟flattenMap稍微有一點(diǎn)不同,他的block返回值是一個(gè)id類型,而flattenMap是一個(gè)信號(hào)。

也就是說(shuō)不用在返回信號(hào)了,直接返回一個(gè)數(shù)據(jù),返回的數(shù)據(jù)就是處理后的數(shù)據(jù)。

    RACSubject *subject = [RACSubject subject];
    
    RACSignal *signal = [subject map:^id _Nullable(id  _Nullable value) {
        //返回的數(shù)據(jù)就是需要處理的數(shù)據(jù)
        return [NSString stringWithFormat:@"%@123",value];
    }];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    //發(fā)送數(shù)據(jù)
    [subject sendNext:@"我想靜靜"];

運(yùn)行如圖:


image

6.2 組合

concat:按順序組合。
剛剛我們說(shuō)到了rac_liftSelector的使用場(chǎng)景,它是在等多個(gè)信號(hào)全部都返回?cái)?shù)據(jù)后再刷新UI。那么我們現(xiàn)在有一個(gè)需求,就是按順序刷新UI,也就是說(shuō)你這些接口什么時(shí)候請(qǐng)求完數(shù)據(jù)我并不知道,但是你請(qǐng)求完成后的處理要按照我的順序來(lái)。處理完第一個(gè),再處理第二個(gè)。

    //組合!!
    //創(chuàng)建信號(hào)!!
    RACSignal * signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"發(fā)送請(qǐng)求A");
        //發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"數(shù)據(jù)A"];
        //哥么結(jié)束了!!
        [subscriber sendCompleted];
        //[subscriber sendError:nil];
        return nil;
    }];
    
    RACSignal * signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"發(fā)送請(qǐng)求B");
        //發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"數(shù)據(jù)B"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    RACSignal * signalC = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"發(fā)送請(qǐng)求C");
        //發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"數(shù)據(jù)C"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    //concat:按順序組合!!
    //創(chuàng)建組合信號(hào)!!
    RACSignal * concatSignal = [RACSignal concat:@[signalA,signalB,signalC]];
    
    //訂閱組合信號(hào)
    [concatSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

運(yùn)行如圖:


image

then:

忽略掉前面一個(gè)信號(hào)所有的值,返回后一個(gè)信號(hào)的數(shù)據(jù)。也就是說(shuō)后一個(gè)信號(hào)的數(shù)據(jù)要依賴前一個(gè)信號(hào)的發(fā)送完畢,但我并不需要處理前一個(gè)信號(hào)的數(shù)據(jù)。

    //創(chuàng)建信號(hào)!!
    RACSignal * signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"發(fā)送請(qǐng)求A");
        //發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"數(shù)據(jù)A"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    RACSignal * signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"發(fā)送請(qǐng)求B");
        //發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"數(shù)據(jù)B"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    //then:忽略掉第一個(gè)信號(hào)所有的值!!
    RACSignal * thenSignal = [signalA then:^RACSignal * _Nonnull{
        return signalB;
    }];
    
    //訂閱信號(hào)
    [thenSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

運(yùn)行如圖:


image

merge: 無(wú)序組合,誰(shuí)先發(fā)送誰(shuí)先處理。

前面我說(shuō)到的都是有序的,那么肯定也有無(wú)序的組合,假設(shè)我們一般頁(yè)面有N多個(gè)接口的請(qǐng)求,需要來(lái)一個(gè)就顯示一個(gè)。處理的代碼呢也能寫到一起。

    //創(chuàng)建信號(hào)
    RACSubject * signalA = [RACSubject subject];
    RACSubject * signalB = [RACSubject subject];
    RACSubject * signalC = [RACSubject subject];
    
    //組合信號(hào)
    RACSignal * mergeSignal = [RACSignal merge:@[signalA,signalB,signalC]];
    
    //訂閱 -- 根據(jù)發(fā)送的情況接受數(shù)據(jù)!!
    [mergeSignal subscribeNext:^(id  _Nullable x) {
        //任意一二信號(hào)發(fā)送內(nèi)容就會(huì)來(lái)這個(gè)Block
        NSLog(@"%@",x);
    }];
    
    //發(fā)送數(shù)據(jù)
    [signalC sendNext:@"數(shù)據(jù)C"];
    [signalA sendNext:@"數(shù)據(jù)A"];
    [signalB sendNext:@"數(shù)據(jù)B"];

運(yùn)行如圖:


image

zipWith:

兩個(gè)信號(hào)壓縮!只有當(dāng)兩個(gè)信號(hào)同時(shí)發(fā)出信號(hào)內(nèi)容,并且將內(nèi)容合并成為一個(gè)元祖給你

    //創(chuàng)建信號(hào)
    RACSubject * signalA = [RACSubject subject];
    RACSubject * signalB = [RACSubject subject];
    
    //壓縮
    RACSignal * zipSignal =  [signalA zipWith:signalB];
    
    //接受數(shù)據(jù)  和發(fā)送順序無(wú)關(guān)!!
    [zipSignal subscribeNext:^(id  _Nullable x) {
        RACTupleUnpack(NSString *str1,NSString *str2) = x;
        NSLog(@"str1=%@,str2=%@",str1,str2);
    }];
    //發(fā)送數(shù)據(jù)
    //這是一組
    [signalB sendNext:@"小明"];
    [signalA sendNext:@"小小"];
    //這也是一組
    [signalB sendNext:@"小明1"];
    [signalA sendNext:@"小小1"];
    //這也是一組
    [signalB sendNext:@"小明2"];
    [signalA sendNext:@"小小2"];

運(yùn)行如圖:

image

這里 只有signalA、signalB同時(shí)發(fā)送了一次信號(hào),才會(huì)接收到信號(hào),接收到的數(shù)據(jù)是一個(gè)元祖,值就是signalAsignalB發(fā)送的數(shù)據(jù)。

元祖的數(shù)據(jù)順序和你發(fā)送的順序無(wú)關(guān),而是和[signalA zipWith:signalB]這個(gè)方法有關(guān)。

combineLatest: reduce:

組合信號(hào),將多個(gè)信號(hào)的數(shù)據(jù)進(jìn)行合并處理,在返回一個(gè)數(shù)據(jù)給新的信號(hào)。

這個(gè)東西呢,我們我們通過(guò)一個(gè)例子來(lái)說(shuō)明,就拿一個(gè)簡(jiǎn)單的登錄來(lái)說(shuō)把。

首先呢有兩個(gè)輸入框(UITextField),賬號(hào)和密碼,還有一個(gè)按鈕(UIButton),首先這個(gè)按鈕是不可點(diǎn)擊的,當(dāng)兩個(gè)輸入框都有值的情況下呢按鈕才可以點(diǎn)擊。

 UITextField *nameTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 64, 200, 50)];
    [self.view addSubview:nameTF];
    nameTF.placeholder = @"請(qǐng)出入昵稱";
    nameTF.backgroundColor = [UIColor yellowColor];
    
    UITextField *pwdTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 120, 200, 50)];
    [self.view addSubview:pwdTF];
    pwdTF.placeholder = @"請(qǐng)出入密碼";
    pwdTF.backgroundColor = [UIColor grayColor];
    
    UIButton *loginBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 180, 100, 50)];
    [self.view addSubview:loginBtn];
    [loginBtn setTitle:@"登錄" forState:UIControlStateNormal];
    [loginBtn setBackgroundColor:[UIColor purpleColor]];
    RACSignal *signalBtn = [loginBtn rac_signalForControlEvents:(UIControlEventTouchUpInside)];
    [signalBtn subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    //組合
    //reduceBlock參數(shù):根據(jù)組合的信號(hào)關(guān)聯(lián)的  必須一一對(duì)應(yīng)!!
    RACSignal * signal = [RACSignal combineLatest:@[nameTF.rac_textSignal,pwdTF.rac_textSignal] reduce:^id _Nullable(NSString *nickName,NSString * pwd){
        
        //兩個(gè)文本框的text是否有值!!
        return @(nickName.length && pwd.length);
    }];
    RAC(loginBtn,enabled) = signal;

運(yùn)行如圖:


image

6.3 過(guò)濾

  • filter: 當(dāng)滿足特定的條件,才能獲取到訂閱的信號(hào)數(shù)據(jù)。
    UITextField *nameTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 64, 200, 50)];
    [self.view addSubview:nameTF];
    nameTF.backgroundColor = [UIColor yellowColor];
    
    RACSignal *signal = [nameTF.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
        if (value.length > 5) {
            return YES;
        }
        return nil;
    }];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

運(yùn)行如圖:


image
  • ignore:忽略掉哪些值。
    UITextField *nameTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 64, 200, 50)];
    [self.view addSubview:nameTF];
    nameTF.backgroundColor = [UIColor yellowColor];
    
    RACSignal *signal = [nameTF.rac_textSignal ignore:@"a"];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

運(yùn)行如圖:

輸入第一個(gè)a并沒(méi)有監(jiān)聽(tīng)到

image
  • take: 指定拿前面的哪幾條數(shù)據(jù)!!(從前往后)
    RACSubject * subject = [RACSubject subject];
    
    //take:指定拿前面的哪幾條數(shù)據(jù)!!(從前往后)
    //takeLast:指定拿后面的哪幾條數(shù)據(jù)!!(從后往前)注意點(diǎn):一定要寫結(jié)束!!
    [[subject take:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    [subject sendNext:@"2"];
    [subject sendNext:@"3"];
    [subject sendNext:@"1"];
    [subject sendCompleted];

運(yùn)行如圖:

image

  • takeLast: 指定拿后面的哪幾條數(shù)據(jù)!!(從后往前)注意點(diǎn):一定要寫結(jié)束!!
    RACSubject * subject = [RACSubject subject];
    
    //take:指定拿前面的哪幾條數(shù)據(jù)!!(從前往后)
    //takeLast:指定拿后面的哪幾條數(shù)據(jù)!!(從后往前)注意點(diǎn):一定要寫結(jié)束!!
    [[subject takeLast:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    [subject sendNext:@"2"];
    [subject sendNext:@"3"];
    [subject sendNext:@"1"];
    [subject sendCompleted];

運(yùn)行如圖:

image

  • takeUntil:直到你的標(biāo)記信號(hào)發(fā)送數(shù)據(jù)的時(shí)候結(jié)束!!!
    RACSubject * subject = [RACSubject subject];
    //專門做一個(gè)標(biāo)記信號(hào)!!
    RACSubject * signal = [RACSubject subject];
    
    //takeUntil:直到你的標(biāo)記信號(hào)發(fā)送數(shù)據(jù)的時(shí)候結(jié)束!!!
    [[subject takeUntil:signal] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    
    [subject sendNext:@"2"];
    [subject sendNext:@"靜靜"];
    [signal sendNext:@"小明"];//這個(gè)信號(hào)發(fā)送之后就結(jié)束了。
//    [signal sendCompleted];//標(biāo)記信號(hào)!! 這個(gè)信號(hào)發(fā)送之后也一樣結(jié)束。
    
    [subject sendNext:@"3"];
    [subject sendNext:@"1"];
    [subject sendCompleted];

當(dāng)signal發(fā)送信號(hào)后,subject的發(fā)送就會(huì)結(jié)束,這里的 3 1 就不會(huì)在發(fā)送了。這種方式也比較常用。

運(yùn)行如圖:

image

  • distinct:忽略掉重復(fù)數(shù)據(jù)
//1.創(chuàng)建信號(hào)
    RACSubject * subject = [RACSubject subject];
    
    //忽略掉重復(fù)數(shù)據(jù)
    [[subject distinctUntilChanged] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    //發(fā)送
    [subject sendNext:@"小明"];
    [subject sendNext:@"小明"];
    [subject sendNext:@"小小"];
    [subject sendNext:@"小愛(ài)"];

運(yùn)行如圖:

image

這樣可以吧。。我們換個(gè)順序好了

看圖:

image

依舊是兩個(gè)小明,不太靠譜吧

  • skip: 跳躍幾個(gè)值
    RACSubject * subject = [RACSubject subject];
    
    //skip: 跳躍幾個(gè)值
    [[subject skip:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    [subject sendNext:@"小明"];
    [subject sendNext:@"小小"];
    [subject sendNext:@"小紅帽"];
    [subject sendNext:@"小愛(ài)"];
    [subject sendNext:@"小不點(diǎn)"];
    [subject sendNext:@"大灰狼"];

運(yùn)行如圖:


image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容