6 RAC終結(jié)篇
6.1 映射
RAC
的映射主要有兩個方法(flattenMap
map
)搜吧,這兩個方法主要用于將信號源的內(nèi)容映射成為一個新的信號景用。
-
flattenMap
它其實也是綁定信號劫侧,一般用于信號中的信號。
RACSubject *subject = [RACSubject subject];
RACSignal *signal = [subject flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
value = [NSString stringWithFormat:@"處理數(shù)據(jù):%@",value];
//返回信號用來包裝修改過的內(nèi)容
return [RACReturnSignal return:value];
}];
//訂閱綁定信號
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//發(fā)送數(shù)據(jù)
[subject sendNext:@"123"];
運行如圖:
看起來有點繞葵礼,說白了我們在什么場景下會用到這種呢?
就在我們發(fā)送的數(shù)據(jù)虫蝶,需要對數(shù)據(jù)進行處理然后再訂閱這個信號的時候就可以使用這種方式章咧,其實跟我們上一節(jié)中提到的
bind
是一樣的。
- map
這個方法跟flattenMap
稍微有一點不同能真,他的block
返回值是一個id
類型赁严,而flattenMap
是一個信號。
也就是說不用在返回信號了粉铐,直接返回一個數(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:@"我想靜靜"];
運行如圖:
6.2 組合
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"];
[subscriber sendCompleted];
return nil;
}];
//concat:按順序組合!!
//創(chuàng)建組合信號!!
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 = [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:
兩個信號壓縮!只有當兩個信號同時發(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) {
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"];
運行如圖:
這里 只有
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
)远寸,首先這個按鈕是不可點擊的,當兩個輸入框都有值的情況下呢按鈕才可以點擊屠凶。
UITextField *nameTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 64, 200, 50)];
[self.view addSubview:nameTF];
nameTF.placeholder = @"請出入昵稱";
nameTF.backgroundColor = [UIColor yellowColor];
UITextField *pwdTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 120, 200, 50)];
[self.view addSubview:pwdTF];
pwdTF.placeholder = @"請出入密碼";
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ù)組合的信號關(guān)聯(lián)的 必須一一對應(yīng)!!
RACSignal * signal = [RACSignal combineLatest:@[nameTF.rac_textSignal,pwdTF.rac_textSignal] reduce:^id _Nullable(NSString *nickName,NSString * pwd){
//兩個文本框的text是否有值!!
return @(nickName.length && pwd.length);
}];
RAC(loginBtn,enabled) = signal;
運行如圖:
6.3 過濾
- filter: 當滿足特定的條件驰后,才能獲取到訂閱的信號數(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);
}];
運行如圖:
- 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);
}];
運行如圖:
輸入第一個a
并沒有監(jiān)聽到
- take: 指定拿前面的哪幾條數(shù)據(jù)!!(從前往后)
RACSubject * subject = [RACSubject subject];
//take:指定拿前面的哪幾條數(shù)據(jù)!!(從前往后)
//takeLast:指定拿后面的哪幾條數(shù)據(jù)!!(從后往前)注意點:一定要寫結(jié)束!!
[[subject take:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"2"];
[subject sendNext:@"3"];
[subject sendNext:@"1"];
[subject sendCompleted];
運行如圖:
- 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:直到你的標記信號發(fā)送數(shù)據(jù)的時候結(jié)束!!!
RACSubject * subject = [RACSubject subject];
//專門做一個標記信號!!
RACSubject * signal = [RACSubject subject];
//takeUntil:直到你的標記信號發(fā)送數(shù)據(jù)的時候結(jié)束!!!
[[subject takeUntil:signal] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"2"];
[subject sendNext:@"靜靜"];
[signal sendNext:@"小明"];//這個信號發(fā)送之后就結(jié)束了灶芝。
// [signal sendCompleted];//標記信號!! 這個信號發(fā)送之后也一樣結(jié)束。
[subject sendNext:@"3"];
[subject sendNext:@"1"];
[subject sendCompleted];
當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:@"小明"];
[subject sendNext:@"小明"];
[subject sendNext:@"小小"];
[subject sendNext:@"小愛"];
運行如圖:
這樣可以吧女器。。我們換個順序好了
看圖:
依舊是兩個小明春塌,不太靠譜吧
- skip: 跳躍幾個值
RACSubject * subject = [RACSubject subject];
//skip: 跳躍幾個值
[[subject skip:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"小明"];
[subject sendNext:@"小小"];
[subject sendNext:@"小紅帽"];
[subject sendNext:@"小愛"];
[subject sendNext:@"小不點"];
[subject sendNext:@"大灰狼"];
運行如圖: