RAC映射
RAC的映射主要有兩個(gè)方法(flattenMap map),這兩個(gè)方法主要用于將信號(hào)源的內(nèi)容映射成為一個(gè)新的信號(hào)。
- flattenMap:它其實(shí)也是綁定信號(hào),一般用于信號(hào)中的信號(hào)。
//創(chuàng)建信號(hào)
RACSubject * subject = [RACSubject subject];
//綁定信號(hào)
RACSignal * bindSignal = [subject flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
//block:只要源信號(hào)發(fā)送內(nèi)容就會(huì)調(diào)用
//value:就是源信號(hào)發(fā)送的內(nèi)容
value = [NSString stringWithFormat:@"處理數(shù)據(jù):%@",value];
//返回信號(hào)用來包裝修改過的內(nèi)容
return [RACReturnSignal return:value];
}];
//訂閱綁定信號(hào)
[bindSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
[subject sendNext:@"123"];
看起來有點(diǎn)繞,說白了我們在什么場景下會(huì)用到這種呢?就在我們發(fā)送的數(shù)據(jù),需要對數(shù)據(jù)進(jìn)行處理然后再訂閱這個(gè)信號(hào)的時(shí)候就可以使用這種方式,其實(shí)跟我們上一節(jié)中提到的 bind 是一樣的。
flattenMap一般用于處理信號(hào)中的信號(hào)。
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ā)送信號(hào)
[signalOfSignal sendNext:signal];
[signal sendNext:@"123"];
- map:這個(gè)方法呢 跟flattenMap稍微有一點(diǎn)不同,他的block返回值是一個(gè)id類型,而flattenMap是一個(gè)信號(hào)。也就是說不用在返回信號(hào)了,直接返回一個(gè)數(shù)據(jù),返回的數(shù)據(jù)就是處理后的數(shù)據(jù)。
//創(chuàng)建信號(hào)
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 的使用場景,它是在等多個(gè)信號(hào)全部都返回?cái)?shù)據(jù)后再刷新UI。那么我們現(xiàn)在有一個(gè)需求,就是按順序刷新UI,也就是說你這些接口什么時(shí)候請求完數(shù)據(jù)我并不知道,但是你請求完成后的處理要按照我的順序來。處理完第一個(gè),再處理第二個(gè)。
//組合!!
//創(chuàng)建信號(hào)!!
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)建組合信號(hào)!!
//RACSignal * concatSignal = [[signalA concat:signalB] concat:signalC];
RACSignal * concatSignal = [RACSignal concat:@[signalA,signalB,signalC]];
//訂閱組合信號(hào)
[concatSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
- then:忽略掉前面一個(gè)信號(hào)所有的值,返回后一個(gè)信號(hào)的數(shù)據(jù)。也就是說后一個(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ā)送請求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:忽略掉第一個(gè)信號(hào)所有的值!!
RACSignal * thenSignal = [signalA then:^RACSignal * _Nonnull{
return signalB;
}];
//訂閱信號(hào)
[thenSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
- merge:無序組合,誰先發(fā)送誰先處理。
前面我說到的都是有序的,那么肯定也有無序的組合,假設(shè)我們一般頁面有N多個(gè)接口的請求,需要來一個(gè)就顯示一個(gè)。處理的代碼呢也能寫到一起。
//創(chuàng)建信號(hào)
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
RACSubject * signalC = [RACSubject subject];
//組合信號(hào)
//RACSignal * mergeSignal = [signalA merge:signalB];
RACSignal * mergeSignal = [RACSignal merge:@[signalA,signalB,signalC]];
//訂閱 -- 根據(jù)發(fā)送的情況接受數(shù)據(jù)!!
[mergeSignal subscribeNext:^(id _Nullable x) {
//任意一二信號(hào)發(fā)送內(nèi)容就會(huì)來這個(gè)Block
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
[signalC sendNext:@"數(shù)據(jù)C"];
[signalA sendNext:@"數(shù)據(jù)A"];
[signalB sendNext:@"數(shù)據(jù)B"];
- 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ā)送順序無關(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同時(shí)發(fā)送了一次信號(hào),才會(huì)接收到信號(hào),接收到的數(shù)據(jù)是一個(gè)元祖,值就是signalA、signalB發(fā)送的數(shù)據(jù)。元祖的數(shù)據(jù)順序和你發(fā)送的順序無關(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è)東西呢,我們我們通過一個(gè)例子來說明,就拿一個(gè)簡單的登錄來說把。首先呢有兩個(gè)輸入框(UITextField),賬號(hào)和密碼,還有一個(gè)按鈕(UIButton),首先這個(gè)按鈕是不可點(diǎn)擊的,當(dāng)兩個(gè)輸入框都有值的情況下呢按鈕才可以點(diǎn)擊。
//組合
//reduceBlock參數(shù):根據(jù)組合的信號(hào)關(guān)聯(lián)的 必須 一一對應(yīng)!!
RACSignal * signal = [RACSignal combineLatest:@[_accountFiled.rac_textSignal,_pwdFiled.rac_textSignal] reduce:^id _Nullable(NSString * account,NSString * pwd){
//兩個(gè)文本框的text是否有值!!
return @(account.length && pwd.length);
}];
RAC(_loginBtn,enabled) = signal;
這樣來看,就不難理解了吧。
RAC過濾
- filter:當(dāng)滿足特定的條件,才能獲取到訂閱的信號(hào)數(shù)據(jù)。
[[_textfiled.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
//value:源信號(hào)的內(nèi)容
return [value length] > 5;
//返回值:就是過濾條件,只有滿足這個(gè)條件,才能獲取到內(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ù)!!(從后往前)注意點(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];
- 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"];
//[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ā)送了。這種方式也比較常用。
- 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:@"1"];
[subject sendNext:@"1"];
[subject sendNext:@"2"];
[subject sendNext:@"2"];
這里 有 1 2 都有重復(fù)的,所以這里只會(huì)打印 1 2。
- skip: 跳躍幾個(gè)值
RACSubject * subject = [RACSubject subject];
//skip: 跳躍幾個(gè)值
[[subject skip:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"1"];
[subject sendNext:@"2"];
[subject sendNext:@"3"];
這里就跳過了 1 2 ,所以只能打印 3。