ReactiveCocoa 實(shí)用指南之進(jìn)階

上篇RAC入門(mén)的文章相信大家都已經(jīng)比較了解了,下面就給大家介紹RAC比較高級(jí)的東西。

1.創(chuàng)建信號(hào)

// RACSignal使用步驟:
    // 1.創(chuàng)建信號(hào) + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
    // 2.訂閱信號(hào),才會(huì)激活信號(hào). - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
    // 3.發(fā)送信號(hào) - (void)sendNext:(id)value
    
    // RACSignal底層實(shí)現(xiàn):
    // 1.創(chuàng)建信號(hào),首先把didSubscribe保存到信號(hào)中,還不會(huì)觸發(fā)。
    // 2.當(dāng)信號(hào)被訂閱,也就是調(diào)用signal的subscribeNext:nextBlock
    // 2.2 subscribeNext內(nèi)部會(huì)創(chuàng)建訂閱者subscriber,并且把nextBlock保存到subscriber中。
    // 2.1 subscribeNext內(nèi)部會(huì)調(diào)用siganl的didSubscribe
    // 3.siganl的didSubscribe中調(diào)用[subscriber sendNext:@1];
    // 3.1 sendNext底層其實(shí)就是執(zhí)行subscriber的nextBlock
    
    // 1.創(chuàng)建信號(hào)
    RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        // block調(diào)用時(shí)刻:每當(dāng)有訂閱者訂閱信號(hào),就會(huì)調(diào)用block。
        
        // 2.發(fā)送信號(hào)
        [subscriber sendNext:@1];
        
        // 如果不在發(fā)送數(shù)據(jù),最好發(fā)送信號(hào)完成,內(nèi)部會(huì)自動(dòng)調(diào)用[RACDisposable disposable]取消訂閱信號(hào)。
        [subscriber sendCompleted];
        
        return [RACDisposable disposableWithBlock:^{
            
            // block調(diào)用時(shí)刻:當(dāng)信號(hào)發(fā)送完成或者發(fā)送錯(cuò)誤,就會(huì)自動(dòng)執(zhí)行這個(gè)block,取消訂閱信號(hào)。
            
            // 執(zhí)行完Block后,當(dāng)前信號(hào)就不在被訂閱了。
            
            NSLog(@"信號(hào)被銷毀");
            
        }];
    }];
    
    // 3.訂閱信號(hào),才會(huì)激活信號(hào).
    [siganl subscribeNext:^(id x) {
        // block調(diào)用時(shí)刻:每當(dāng)有信號(hào)發(fā)出數(shù)據(jù),就會(huì)調(diào)用block.
        NSLog(@"接收到數(shù)據(jù):%@",x);
    }];


2.信號(hào)的處理:

filter:過(guò)濾前綴包含“mei”的字符串

 [[mytextField.rac_textSignal filter:^BOOL(NSString *value) {
        return [value hasPrefix:@"mei"];
    }] subscribeNext:^(NSString *value) {
        NSLog(@"This value has prefix `mei` : %@", value);
    }];
    

ignore:忽略前綴包含“mei”的字符串

 [[mytextField.rac_textSignal ignore:@"mei"] subscribeNext:^(NSString *value) {
        NSLog(@"`mei` could never appear : %@", value);
    }];

take:取前兩個(gè)

 [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"1"];
        [subscriber sendNext:@"2"];
        [subscriber sendNext:@"3"];
        [subscriber sendCompleted];
        return nil;
    }] take:2] subscribeNext:^(id x) {
        NSLog(@"only 1 and 2 will be print: %@", x);
    }];


skip:跳過(guò)第一個(gè)

 
    [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"1"];
        [subscriber sendNext:@"2"];
        [subscriber sendNext:@"3"];
        [subscriber sendCompleted];
        return nil;
    }] skip:1] subscribeNext:^(id x) {
        NSLog(@"only 2 and 3 will be print: %@", x);
    }];

throttle:節(jié)流
可能大家還是不理解,我給大家舉個(gè)例子吧,我們公司曾經(jīng)有一個(gè)需求,當(dāng)用戶再輸入框輸入的文本發(fā)生改變的時(shí)候可以請(qǐng)求數(shù)據(jù),做到及時(shí)搜索的功能。就像百度現(xiàn)在的搜索體驗(yàn)。做到這個(gè)如果不考慮服務(wù)器壓力其實(shí)沒(méi)那么難,但是我們是追求完美的人,怎么能不考慮服務(wù)器性能呢。那么就有一個(gè)問(wèn)題,一旦輸入框發(fā)生改變我們就要從服務(wù)器獲取數(shù)據(jù)嗎,當(dāng)然不能這樣,這里我們?nèi)绻幸粋€(gè)時(shí)間延遲那就最好了,那就是節(jié)流。
這里再介紹一下switchToLatest,當(dāng)我們搜索的時(shí)候下一個(gè)搜索已經(jīng)開(kāi)始了可能上一個(gè)搜索還沒(méi)返回結(jié)果,我們就沒(méi)必要開(kāi)啟上一個(gè)搜索了,肯定是去最新的吧。所以switchToLatest就是這樣的一個(gè)功能。好了,下面就是兩者結(jié)合給我們的搜索優(yōu)化的一段代碼

[[[[[[textField.rac_textSignal throttle:0.3]distinctUntilChanged]ignore:@""] map:^id(id value) {
        
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            //  network request
            [subscriber sendNext:value];
            [subscriber sendCompleted];
            
            return [RACDisposable disposableWithBlock:^{
                
                //  cancel request
            }];
        }];
    }]switchToLatest] subscribeNext:^(id x) {
        
        NSLog(@"x = %@",x);
    }];


repeat:重復(fù)

[[[[[RACSignal createSignal:^RACDisposable *(id subscriber) {
    
    [subscriber sendNext:@"rac"];
    [subscriber sendCompleted];
    
    return nil;
}]delay:1]repeat]take:10] subscribeNext:^(id x) {
    
    NSLog(@"x = %@",x);
} completed:^{
    
    NSLog(@"完成");
}];

merge:合并 同時(shí)訂閱,各自執(zhí)行

  RACSignal * signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"A");
            [subscriber sendNext:@"a"];
            [subscriber sendCompleted];
        });
        
        return nil;
    }];
    
    RACSignal * signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"B");
            [subscriber sendNext:@"b"];
            [subscriber sendCompleted];
        });
        
        return nil;
    }];
    
    [[RACSignal merge:@[signalA, signalB]]subscribeNext:^(id x) {
        
        NSLog(@"x = %@",x);
    }];


concat: 一個(gè)異步請(qǐng)求完成后,再啟動(dòng)另一個(gè)

RACSignal * signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"a");
            [subscriber sendNext:@"a"];
            [subscriber sendCompleted];
        });
        
        return nil;
    }];
    
    RACSignal * signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"b");
            [subscriber sendNext:@"b"];
            [subscriber sendCompleted];
        });
        
        return nil;
    }];
    
    [[signalA concat:signalB]subscribeNext:^(id x) {
        
       NSLog(@"x=%@",x);
    }];


zipWith:/combineLatest: 多個(gè)異步請(qǐng)求都完成后,再做某件事

 RACSignal * signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"a");
            [subscriber sendNext:@"a"];
            [subscriber sendCompleted];
        });
        
        return nil;
    }];
    
    RACSignal * signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"b");
            [subscriber sendNext:@"b"];
            [subscriber sendCompleted];
        });
        
        return nil;
    }];
    
    [[signalA zipWith:signalB]subscribeNext:^(id x) {
        
        NSLog(@"x = %@",x);
    }];



RAC的一些宏


 UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.view addSubview:button];
    button.frame = CGRectMake(100, 100, 180, 40);
    
    RAC(button, backgroundColor) = [RACObserve(button, selected) map:^UIColor *(NSNumber * selected) {
        
        return [selected boolValue] ? [UIColor redColor] : [UIColor greenColor];
    }];
    
    [[button rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(UIButton * btn) {
        
        btn.selected = !btn.selected;
    }];
    


 RAC(showLabel, text) = mytextField.rac_textSignal;

 RAC(showLabel, text) = [[[mytextField.rac_textSignal
                             startWith:@"不足3個(gè)字"] // startWith 一開(kāi)始返回的初始值
                            filter:^BOOL(NSString *value) { // filter使?jié)M足條件的值才能傳出
                                return value.length > 3;
                            }]map:^id(id value) {
                                // map將一個(gè)值轉(zhuǎn)化為另一個(gè)值輸出
                                return [value isEqualToString:@"meiqing"] ? @"驗(yàn)證成功!" : value;
                            }];

如果覺(jué)得文章還不錯(cuò),可以打賞哦。
微博賬號(hào):梅嘉慶(點(diǎn)擊關(guān)注)

最后編輯于
?著作權(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)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,724評(píng)論 19 139
  • 前言由于時(shí)間的問(wèn)題,暫且只更新這么多了,后續(xù)還會(huì)持續(xù)更新本文《最快讓你上手ReactiveCocoa之進(jìn)階篇》,目...
    Karos_凱閱讀 1,875評(píng)論 0 6
  • 打算在項(xiàng)目中大面積使用RAC來(lái)開(kāi)發(fā),所以整理一些常用的實(shí)踐范例和比較完整的api說(shuō)明方便開(kāi)發(fā)時(shí)隨時(shí)查閱 聲明式編程...
    星光社的戴銘閱讀 5,481評(píng)論 5 49
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,290評(píng)論 6 342
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,839評(píng)論 4 61

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