RAC映射
RAC的映射主要有兩個方法(flattenMap map)潘拨,這兩個方法主要用于將信號源的內(nèi)容映射成為一個新的信號惋戏。
- flattenMap:它其實也是綁定信號春贸,一般用于信號中的信號求类。
//創(chuàng)建信號
RACSubject * subject = [RACSubject subject];
//綁定信號
RACSignal * bindSignal = [subject flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
//block:只要源信號發(fā)送內(nèi)容就會調(diào)用
//value:就是源信號發(fā)送的內(nèi)容
value = [NSString stringWithFormat:@"處理數(shù)據(jù):%@",value];
//返回信號用來包裝修改過的內(nèi)容
return [RACReturnSignal return:value];
}];
//訂閱綁定信號
[bindSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
[subject sendNext:@"123"];
看起來有點繞,說白了我們在什么場景下會用到這種呢差凹?就在我們發(fā)送的數(shù)據(jù),需要對數(shù)據(jù)進行處理然后再訂閱這個信號的時候就可以使用這種方式侧馅,其實跟我們上一節(jié)中提到的 bind 是一樣的危尿。
flattenMap一般用于處理信號中的信號。
RACSubject * signalOfSignal = [RACSubject subject];
RACSubject * signal = [RACSubject subject];
[[signalOfSignal flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
return value;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送信號
[signalOfSignal sendNext:signal];
[signal sendNext:@"123"];
- map:這個方法呢 跟flattenMap稍微有一點不同馁痴,他的block返回值是一個id類型脚线,而flattenMap是一個信號。也就是說不用在返回信號了弥搞,直接返回一個數(shù)據(jù)邮绿,返回的數(shù)據(jù)就是處理后的數(shù)據(jù)。
//創(chuàng)建信號
RACSubject * subject = [RACSubject subject];
//綁定
[[subject map:^id _Nullable(id _Nullable value) {
//返回的數(shù)據(jù)就是需要處理的數(shù)據(jù)
return [NSString stringWithFormat:@"處理數(shù)據(jù)%@",value];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
[subject sendNext:@"123"];
RAC組合
- concat:按順序組合攀例。
在上一篇中我們說到了 rac_liftSelector 的使用場景船逮,它是在等多個信號全部都返回數(shù)據(jù)后再刷新UI。那么我們現(xiàn)在有一個需求粤铭,就是按順序刷新UI,也就是說你這些接口什么時候請求完數(shù)據(jù)我并不知道挖胃,但是你請求完成后的處理要按照我的順序來。處理完第一個梆惯,再處理第二個酱鸭。
//組合!!
//創(chuàng)建信號!!
RACSignal * signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"發(fā)送請求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ā)送請求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ā)送請求C");
//發(fā)送數(shù)據(jù)
[subscriber sendNext:@"數(shù)據(jù)C"];
return nil;
}];
//concat:按順序組合!!
//創(chuàng)建組合信號!!
//RACSignal * concatSignal = [[signalA concat:signalB] concat:signalC];
RACSignal * concatSignal = [RACSignal concat:@[signalA,signalB,signalC]];
//訂閱組合信號
[concatSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
- then:忽略掉前面一個信號所有的值,返回后一個信號的數(shù)據(jù)垛吗。也就是說后一個信號的數(shù)據(jù)要依賴前一個信號的發(fā)送完畢凹髓,但我并不需要處理前一個信號的數(shù)據(jù)。
//創(chuàng)建信號!!
RACSignal * signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"發(fā)送請求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ā)送請求B");
//發(fā)送數(shù)據(jù)
[subscriber sendNext:@"數(shù)據(jù)B"];
[subscriber sendCompleted];
return nil;
}];
//then:忽略掉第一個信號所有的值!!
RACSignal * thenSignal = [signalA then:^RACSignal * _Nonnull{
return signalB;
}];
//訂閱信號
[thenSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
- merge:無序組合怯屉,誰先發(fā)送誰先處理蔚舀。
前面我說到的都是有序的饵沧,那么肯定也有無序的組合,假設(shè)我們一般頁面有N多個接口的請求赌躺,需要來一個就顯示一個狼牺。處理的代碼呢也能寫到一起。
//創(chuàng)建信號
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
RACSubject * signalC = [RACSubject subject];
//組合信號
//RACSignal * mergeSignal = [signalA merge:signalB];
RACSignal * mergeSignal = [RACSignal merge:@[signalA,signalB,signalC]];
//訂閱 -- 根據(jù)發(fā)送的情況接受數(shù)據(jù)!!
[mergeSignal subscribeNext:^(id _Nullable x) {
//任意一二信號發(fā)送內(nèi)容就會來這個Block
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
[signalC sendNext:@"數(shù)據(jù)C"];
[signalA sendNext:@"數(shù)據(jù)A"];
[signalB sendNext:@"數(shù)據(jù)B"];
- zipWith:兩個信號壓縮!只有當(dāng)兩個信號同時發(fā)出信號內(nèi)容,并且將內(nèi)容合并成為一個元祖給你
//創(chuàng)建信號
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
//壓縮
RACSignal * zipSignal = [signalA zipWith:signalB];
//接受數(shù)據(jù) 和發(fā)送順序無關(guān)!!
[zipSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
//這是一組
[signalB sendNext:@"B"];
[signalA sendNext:@"A"];
//這也是一組
[signalB sendNext:@"B1"];
[signalA sendNext:@"A1"];
//這也是一組
[signalB sendNext:@"B2"];
[signalA sendNext:@"A2"];
這里 只有signalA礼患、signalB同時發(fā)送了一次信號是钥,才會接收到信號,接收到的數(shù)據(jù)是一個元祖缅叠,值就是signalA咏瑟、signalB發(fā)送的數(shù)據(jù)。元祖的數(shù)據(jù)順序和你發(fā)送的順序無關(guān)痪署,而是和[signalA zipWith:signalB]這個方法有關(guān)码泞。
- combineLatest: reduce: 組合信號,將多個信號的數(shù)據(jù)進行合并處理狼犯,在返回一個數(shù)據(jù)給新的信號余寥。
這個東西呢,我們我們通過一個例子來說明悯森,就拿一個簡單的登錄來說把宋舷。首先呢有兩個輸入框(UITextField),賬號和密碼瓢姻,還有一個按鈕(UIButton)祝蝠,首先這個按鈕是不可點擊的,當(dāng)兩個輸入框都有值的情況下呢按鈕才可以點擊幻碱。
//組合
//reduceBlock參數(shù):根據(jù)組合的信號關(guān)聯(lián)的 必須 一一對應(yīng)!!
RACSignal * signal = [RACSignal combineLatest:@[_accountFiled.rac_textSignal,_pwdFiled.rac_textSignal] reduce:^id _Nullable(NSString * account,NSString * pwd){
//兩個文本框的text是否有值!!
return @(account.length && pwd.length);
}];
RAC(_loginBtn,enabled) = signal;
這樣來看绎狭,就不難理解了吧。
RAC過濾
- filter:當(dāng)滿足特定的條件褥傍,才能獲取到訂閱的信號數(shù)據(jù)儡嘶。
[[_textfiled.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
//value:源信號的內(nèi)容
return [value length] > 5;
//返回值:就是過濾條件,只有滿足這個條件,才能獲取到內(nèi)容
}] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@",x);
}];
- ignore:忽略掉哪些值。
RACSubject * subject = [RACSubject subject];
//忽略一些值!!
RACSignal * ignoreSignal = [[[subject ignore:@"1"] ignore:@"2"] ignore:@"3"];
//訂閱
[ignoreSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
[subject sendNext:@"1"];
[subject sendNext:@"2"];
[subject sendNext:@"13"];
[subject sendNext:@"3"];
這里 1 2 3 就被忽略掉了恍风,所以打印的就是13蹦狂。
- take:指定拿前面的哪幾條數(shù)據(jù)!!(從前往后)
- takeLast:指定拿后面的哪幾條數(shù)據(jù)!!(從后往前)注意點:一定要寫結(jié)束!!
RACSubject * subject = [RACSubject subject];
//take:指定拿前面的哪幾條數(shù)據(jù)!!(從前往后)
//takeLast:指定拿后面的哪幾條數(shù)據(jù)!!(從后往前)注意點:一定要寫結(jié)束!!
[[subject takeLast:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"2"];
[subject sendNext:@"3"];
[subject sendNext:@"1"];
[subject sendCompleted];
- takeUntil:直到你的標(biāo)記信號發(fā)送數(shù)據(jù)的時候結(jié)束!!!
RACSubject * subject = [RACSubject subject];
//專門做一個標(biāo)記信號!!
RACSubject * signal = [RACSubject subject];
//takeUntil:直到你的標(biāo)記信號發(fā)送數(shù)據(jù)的時候結(jié)束!!!
[[subject takeUntil:signal] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"2"];
//[signal sendNext:@".."];//這個信號發(fā)送之后就結(jié)束了。
[signal sendCompleted];//標(biāo)記信號!! 這個信號發(fā)送之后也一樣結(jié)束朋贬。
[subject sendNext:@"3"];
[subject sendNext:@"1"];
[subject sendCompleted];
當(dāng)signal發(fā)送信號后凯楔,subject的發(fā)送就會結(jié)束,這里的 3 1 就不會在發(fā)送了锦募。這種方式也比較常用摆屯。
- distinct:忽略掉重復(fù)數(shù)據(jù)
//1.創(chuàng)建信號
RACSubject * subject = [RACSubject subject];
//忽略掉重復(fù)數(shù)據(jù)
[[subject distinctUntilChanged] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送
[subject sendNext:@"1"];
[subject sendNext:@"1"];
[subject sendNext:@"2"];
[subject sendNext:@"2"];
這里 有 1 2 都有重復(fù)的,所以這里只會打印 1 2御滩。
- skip: 跳躍幾個值
RACSubject * subject = [RACSubject subject];
//skip: 跳躍幾個值
[[subject skip:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"1"];
[subject sendNext:@"2"];
[subject sendNext:@"3"];
這里就跳過了 1 2 鸥拧,所以只能打印 3党远。