1.ReactiveCocoa操作方法之映射(flattenMap,Map)
flattenMap,Map:用于把原信號中的內(nèi)容映射成新的內(nèi)容
flattenMap的作用:把原信號的內(nèi)容映射成一個(gè)新的信號,信號可以是任意的類型
flattenMap使用步驟:
1.傳入一個(gè)block,block類型是返回值RACStream,參數(shù)value
2.參數(shù)value就是源信號的內(nèi)容,拿到源信號的內(nèi)容做處理
3.包裝成RACReturnSignal信號,返回出去。
[[self.textfield.rac_textSignal flattenMap:^RACStream *(id value) {
//這個(gè)block什么時(shí)候調(diào)用:原信號發(fā)送數(shù)據(jù)的時(shí)候就會調(diào)用這個(gè)block
//block的作用:改變原信號的內(nèi)容
return [RACReturnSignal return:value];
}] subscribeNext:^(id x) {
// 訂閱綁定信號,每當(dāng)原信號發(fā)送內(nèi)容,做完處理就會調(diào)用這個(gè)block
NSLog(@"%@",x);
}];
flattenMap底層實(shí)現(xiàn):
1.flattenMap內(nèi)部調(diào)用bind方法實(shí)現(xiàn)的,flattenMap中block的返回值,會作為bind中bindBlock的返回值。
2.當(dāng)訂閱綁定信號,就會生成bindBlock。
3.當(dāng)源信號發(fā)送內(nèi)容,就會調(diào)用bindBlock(value, *stop)
4.調(diào)用bindBlock,內(nèi)部就會調(diào)用flattenMap的block,flattenMap的block作用:就是把處理好的數(shù)據(jù)包裝成信號。
5.返回的信號最終會作為bindBlock中的返回信號,當(dāng)做bindBlock的返回信號。
6.訂閱bindBlock的返回信號,就會拿到綁定信號的訂閱者,把處理完成的信號內(nèi)容發(fā)送出來。
Map:監(jiān)聽文本框的內(nèi)容的改變,把結(jié)構(gòu)重新映射成一個(gè)新的值
Map的作用:把原信號的值映射成一個(gè)新的值
Map使用步驟:
1.傳入一個(gè)block,類型是返回對象,參數(shù)是value
2.value就是源信號的內(nèi)容,直接拿到源信號的內(nèi)容做處理
3.把處理好的內(nèi)容直接返回,不用包裝成信號,返回的值就是映射的值
// 創(chuàng)建信號
RACSubject *subject = [RACSubject subject];
RACSignal *signal = [subject map:^id(id value) {
// 當(dāng)原信號發(fā)送數(shù)據(jù)的時(shí)候就會來調(diào)用這個(gè)block,修改原信號的內(nèi)容
value = @([value floatValue] +1.0);
// 返回值就是修改后的原信號的內(nèi)容
return value;
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"999”];
Map:底層實(shí)現(xiàn)
1.Map底層其實(shí)是調(diào)用flatternMap,Map中block中的返回的值會作為flatternMap中block中的值
2.當(dāng)訂閱綁定信號,就會生成bindBlock。
3.當(dāng)源信號發(fā)送內(nèi)容,就會調(diào)用bindBlock(value, *stop)
4.調(diào)用bindBlock,內(nèi)部就會調(diào)用flattenMap的block
5.flattenMap的block內(nèi)部會調(diào)用Map中的block,把Map中的block返回的內(nèi)容包裝成返回的信號。
6.返回的信號最終會作為bindBlock中的返回信號,當(dāng)做bindBlock的返回信號
7.訂閱bindBlock的返回信號,就會拿到綁定信號的訂閱者,把處理完成的信號內(nèi)容發(fā)送出來。
FlatternMap和Map的區(qū)別:
1.FlatternMap中的Block返回信號
2.Map中的Block返回對象
3.開發(fā)中,如果信號發(fā)出的值不是信號,映射一般使用Map
4.開發(fā)中,如果信號發(fā)出的值是信號,映射一般使用FlatternMap
2.ReactiveCocoa操作方法組合
concat:按一定順序拼接信號,當(dāng)多個(gè)信號發(fā)出的時(shí)候有順序的接受信號。
RACSubject *subjectA = [RACSubject subject];
RACSubject *subjectB = [RACSubject subject];
//把subjectA拼接到subjectB的時(shí)候只有subjectA發(fā)送完畢之后subjectB才會被激活
// 只需要訂閱拼接之后的信號,不在需要單獨(dú)拼接subjectA或者subjectB,內(nèi)部會自動訂閱
[[subjectA concat:subjectB] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subjectA sendNext:@"subjectA發(fā)送完信號"];
// 第一個(gè)信號發(fā)送完成,第二個(gè)信號才會被激活
[subjectA sendCompleted];
[subjectB sendNext:@"subjectB發(fā)送完信號”];
concat底層實(shí)現(xiàn):
1.當(dāng)拼接信號被訂閱,就會調(diào)用拼接信號的didSubscribe
2.didSubscribe中,會先訂閱第一個(gè)源信號(subjectA)
3.會執(zhí)行第一個(gè)源信號(subjectA)的didSubscribe
4.第一個(gè)源信號(subjectA)didSubscribe中發(fā)送值,就會調(diào)用第一個(gè)源信號(subjectA)訂閱者的nextBlock,通過拼接信號的訂閱者把值發(fā)送出來.
5.第一個(gè)源信號(subjectA)didSubscribe中發(fā)送完成,就會調(diào)用第一個(gè)源信號(subjectA)訂閱者的completedBlock,訂閱第二個(gè)源信號(subjectB)這時(shí)候才激活(subjectB)
6.訂閱第二個(gè)源信號(subjectB),執(zhí)行第二個(gè)源信號(subjectB)的didSubscribe
7.第二個(gè)源信號(subjectA)didSubscribe中發(fā)送值,就會通過拼接信號的訂閱者把值發(fā)送出來
then:用于連接兩個(gè)信號,當(dāng)?shù)谝粋€(gè)信號完成才會連接then返回的信號
使用then之前的信號會被忽略掉
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"signalA發(fā)送完信號"];
//發(fā)送完畢
[subscriber sendCompleted];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"signalB發(fā)送完信號"];
return nil;
}];
RACSignal *thensignal = [signalA then:^RACSignal *{
return signalB;
}];
[thensignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
底層實(shí)現(xiàn):1、先過濾掉之前的信號發(fā)出的值。2.使用concat連接then返回的信號
merge:把多個(gè)信號合并為一個(gè)信號,任何一個(gè)信號有新值時(shí)就會調(diào)用
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"signalA發(fā)送完信號"];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"signalB發(fā)送完信號"];
return nil;
}];
// 合并信號,任何一個(gè)信號發(fā)送數(shù)據(jù)都能在訂閱中監(jiān)聽到
RACSignal *mergesignal = [signalA merge:signalB];
[mergesignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
底層實(shí)現(xiàn):1.合并信號被訂閱的時(shí)候就會遍歷所有信號,并且發(fā)出這些信號
2.每發(fā)出一個(gè)信號,這個(gè)信號就會被訂閱
3.也就是合并信號一被訂閱,就會訂閱里面所有的信號
4.只要有一個(gè)信號發(fā)出就會被監(jiān)聽
zipWith:把兩個(gè)信號壓縮成一個(gè)信號,只有當(dāng)兩個(gè)信號同時(shí)發(fā)出信號內(nèi)容的時(shí)候,并且把兩個(gè)信號的內(nèi)容合并成一個(gè)元組,才會觸發(fā)壓縮流的next事件
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
//發(fā)送完畢
// [subscriber sendCompleted];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
return nil;
}];
//訂閱中的數(shù)據(jù)和zip的順序相關(guān)。
RACSignal *zipWithsignal = [signalA zipWith:signalB];
[zipWithsignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
底層實(shí)現(xiàn):
1.定義壓縮信號,內(nèi)部就會自動訂閱signalA和signalB
2.每當(dāng)signalA或者signalB發(fā)出信號,就會判斷signalA,signalB有沒有發(fā)出個(gè)信號,有就會把最近發(fā)出的信號都包裝成元組發(fā)出
combineLatest:將多個(gè)信號合并起來,并且拿到各個(gè)信號的最新值,必須每個(gè)合并的signal至少都有過一次sendNext,才會觸發(fā)合并的信號
//把兩個(gè)信號組合成一個(gè)信號,跟zip一樣,沒什么區(qū)別
[[signalA combineLatestWith:signalB] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
底層實(shí)現(xiàn):
1.當(dāng)組合信號被訂閱,內(nèi)部會自動訂閱signalA,被觸發(fā)signalB必須兩個(gè)信號都發(fā)出內(nèi)容,才會被觸發(fā)
2.并且把兩個(gè)信號組合成元組發(fā)出
reduce聚合:用于信號發(fā)出的內(nèi)容是元組,把信號發(fā)出元組的值聚合成一個(gè)值。
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
return nil;
}];
// NSArray是遵守這個(gè)NSFastEnumeration協(xié)議的
//reduce中的block簡介
//reduceblcok中的參數(shù),有多少信號組合reduceblcok中就有多少參數(shù),每個(gè)參數(shù)就是之前信號發(fā)出的內(nèi)容,參數(shù)順序和數(shù)組中的 參數(shù)一一對應(yīng)
//reduceblcok的返回值:聚合信號之后的內(nèi)容
RACSignal *reducesignal = [RACSignal combineLatest:@[signalB,signalA] reduce:^id(NSString *str1,NSString *str2){
return [NSString stringWithFormat:@"%@ -- %@",str1,str2];
}];
[reducesignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
訂閱聚合信號,每次有內(nèi)容發(fā)出就會執(zhí)行reduceblcok,把信號內(nèi)容轉(zhuǎn)換成reduceblcok返回的值。
不正確之處,歡迎補(bǔ)充
測試代碼 https://github.com/CharType/ReactiveCocoaTest