一、參考
- ReactiveCocoa之基礎(chǔ)篇
- ReactiveCocoa之進(jìn)階篇
- 函數(shù)響應(yīng)式編程
- ReactiveCocoa 和 MVVM 入門
- RAC+MVVM在實(shí)際項(xiàng)目中用法
- iOS MVVM+RAC 從框架到實(shí)戰(zhàn)
- iOS Reactivecocoa(RAC)知其所以然(源碼分析,一篇足以)
- RAC核心元素與信號(hào)流
二、常用 方便查找
2.1 UITextField實(shí)時(shí)搜索(throttle
節(jié)流)
這段代碼的意思是若0.3秒內(nèi)無新信號(hào)(tf無輸入),并且輸入框內(nèi)不為空那么將會(huì)執(zhí)行,這對(duì)服務(wù)器的壓力減少有巨大幫助同時(shí)提高了用戶體驗(yàn)
[[[[[[self.searchField.rac_textSignal throttle:0.3] distinctUntilChanged] ignore:@""] map:^id(id value) {
//這里使用的是信號(hào)中的信號(hào)這個(gè)概念
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// network request
// 這里可將請(qǐng)求到的信息發(fā)送出去
[subscriber sendNext:value];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// cancel request
// 這里可以將取消請(qǐng)求寫在這里,若輸入框有新輸入信息那么將會(huì)發(fā)送一個(gè)新的請(qǐng)求,原來那個(gè)沒執(zhí)行完的請(qǐng)求將會(huì)執(zhí)行這個(gè)取消請(qǐng)求的代碼
}];
}];
}]switchToLatest] subscribeNext:^(id x) {
//這里獲取信息
}];
<div id = 'jump'>2.2 RACSignal</div>
//創(chuàng)建信號(hào) 默認(rèn)一個(gè)信號(hào)都是冷信號(hào)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"signal"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
//信號(hào)釋放
}];
}];
//訂閱信號(hào) 訂閱了這個(gè)信號(hào),這個(gè)信號(hào)才會(huì)變?yōu)闊嵝盘?hào)
[signal subscribeNext:^(id x) {
NSLog(@"x == %@",x);
} error:^(NSError *error) {
NSLog(@"error = %@",error);
} completed:^{
NSLog(@"completed");
}];
控制臺(tái)輸出
2017-07-04 22:26:34.677 XXX[3314:53316] x == signal
2017-07-04 22:26:34.677 XXX[3314:53316] completed
2.3 map 和 FlatternMap 映射
1.FlatternMap中的Block返回信號(hào)。
2.Map中的Block返回對(duì)象
3.開發(fā)中,如果信號(hào)發(fā)出的值不是信號(hào),映射一般使用Map
4.開發(fā)中,如果信號(hào)發(fā)出的值是信號(hào),映射一般使用FlatternMap。
[[self.textField.rac_textSignal map:^id(id value) {
return [NSString stringWithFormat:@"pre+%@",value];
}] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
vs
[[self.textField.rac_textSignal flattenMap:^RACStream *(id value) {
return [RACReturnSignal return:[NSString stringWithFormat:@"輸出:%@",value]];;
}] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-04 23:06:24.060 XXX[3796:69496] x == pre+f
2017-07-04 23:06:24.089 XXX[3796:69496] x == pre+fd
2.4 filter
[[self.textField.rac_textSignal filter:^BOOL(id value) {
return [value length] > 3;
}] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-04 23:11:45.563 XXX[3884:71980] x == hell
2017-07-04 23:11:47.111 XXX[3884:71980] x == hello
2.5 take/takeLast/skip
take
獲取信號(hào)的意思
eg: take:2 意思是獲取前兩了信號(hào)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
[[signal take:2] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-05 11:24:11.908 XXX[9717:84530] x == 1
2017-07-05 11:24:11.909 XXX[9717:84530] x == 2
2017-07-05 11:24:11.909 XXX[9717:84530] 信號(hào)釋放
takeLast
是逆序獲取的意思
eg:takeLast:2 是獲取最后兩個(gè)信號(hào)的意思
[[signal takeLast:2] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-05 11:28:30.267 XXX[9839:87189] x == 2
2017-07-05 11:28:30.267 XXX[9839:87189] x == 3
2017-07-05 11:28:30.267 XXX[9839:87189] 信號(hào)釋放
skip
是跳過
eg: skip:2 是跳過前兩個(gè)信號(hào) 從第三個(gè)信號(hào)開始
[[signal skip:2] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-05 11:31:33.308 XXX[9915:88941] x == 3
2017-07-05 11:31:33.309 XXX[9915:88941] 信號(hào)釋放
2.6 distinctUntilChanged
distinctUntilChanged
的作用是使RAC不會(huì)連續(xù)發(fā)送兩次相同的信號(hào)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
[[signal distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-05 12:53:45.642 XXX[10766:118852] x == 1
2017-07-05 12:53:45.643 XXX[10766:118852] x == 2
2017-07-05 12:53:45.643 XXX[10766:118852] x == 3
2017-07-05 12:53:45.643 XXX[10766:118852] x == 1
2017-07-05 12:53:45.643 XXX[10766:118852] 信號(hào)釋放
2.7 ignore
ignore
忽略信號(hào),指定一個(gè)任意類型的量(可以是字符串,數(shù)組等),當(dāng)需要發(fā)送信號(hào)時(shí)講進(jìn)行判斷,若相同則該信號(hào)會(huì)被忽略發(fā)送。
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
[[signal ignore:@"1"] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-05 12:57:46.111 XXX[10849:121171] x == 3
2017-07-05 12:57:46.111 XXX[10849:121171] 信號(hào)釋放
三、ReactiveCocoa操作方法之組合。
3.1 concat
按一定順序拼接信號(hào),當(dāng)多個(gè)信號(hào)發(fā)出的時(shí)候,有順序的接收信號(hào)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)2釋放");
}];
}];
// 把signalA拼接到signalB后,signalA發(fā)送完成,signalB才會(huì)被激活。
RACSignal *concatSignal = [signal concat:signal2];
// 注意:第一個(gè)信號(hào)必須發(fā)送完成,第二個(gè)信號(hào)才會(huì)被激活
[concatSignal subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
3.2 then
用于連接兩個(gè)信號(hào),當(dāng)?shù)谝粋€(gè)信號(hào)完成,才會(huì)連接then返回的信號(hào)。
// then:用于連接兩個(gè)信號(hào),當(dāng)?shù)谝粋€(gè)信號(hào)完成,才會(huì)連接then返回的信號(hào)
// 注意使用then,之前信號(hào)的值會(huì)被忽略掉.
// 底層實(shí)現(xiàn):1、先過濾掉之前的信號(hào)發(fā)出的值。2.使用concat連接then返回的信號(hào)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
[[signal then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)2釋放");
}];
}];
}] subscribeNext:^(id x) {
// 只能接收到第二個(gè)信號(hào)的值,也就是then返回信號(hào)的值
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-05 14:30:57.094 XXX[15627:177519] x == 2
2017-07-05 14:30:57.094 XXX[15627:177519] 信號(hào)釋放
2017-07-05 14:30:57.094 XXX[15627:177519] 信號(hào)2釋放
3.3 merge
把多個(gè)信號(hào)合并為一個(gè)信號(hào),任何一個(gè)信號(hào)有新值的時(shí)候就會(huì)調(diào)用
// merge:把多個(gè)信號(hào)合并成一個(gè)信號(hào)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)2釋放");
}];
}];
// 合并信號(hào),任何一個(gè)信號(hào)發(fā)送數(shù)據(jù),都能監(jiān)聽到.
RACSignal *mergeSignal = [[signal delay:2] merge:signal2];
[mergeSignal subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
// 底層實(shí)現(xiàn):
// 1.合并信號(hào)被訂閱的時(shí)候,就會(huì)遍歷所有信號(hào),并且發(fā)出這些信號(hào)。
// 2.每發(fā)出一個(gè)信號(hào),這個(gè)信號(hào)就會(huì)被訂閱
// 3.也就是合并信號(hào)一被訂閱,就會(huì)訂閱里面所有的信號(hào)。
// 4.只要有一個(gè)信號(hào)被發(fā)出就會(huì)被監(jiān)聽。
控制臺(tái)輸出
2017-07-05 14:45:20.350 XXX[15843:184057] 信號(hào)釋放
2017-07-05 14:45:20.350 XXX[15843:184057] x == 2
2017-07-05 14:45:20.350 XXX[15843:184057] 信號(hào)2釋放
2017-07-05 14:45:22.350 XXX[15843:184057] x == 1
3.4 zipWith
把兩個(gè)信號(hào)壓縮成一個(gè)信號(hào),只有當(dāng)兩個(gè)信號(hào)同時(shí)發(fā)出信號(hào)內(nèi)容時(shí),并且把兩個(gè)信號(hào)的內(nèi)容合并成一個(gè)元組,才會(huì)觸發(fā)壓縮流的next事件。
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)2釋放");
}];
}];
RACSignal *zipSignal = [signal zipWith:signal2];
[zipSignal subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
// 底層實(shí)現(xiàn):
// 1.定義壓縮信號(hào),內(nèi)部就會(huì)自動(dòng)訂閱signal,signal2
// 2.每當(dāng)signal或者signal2發(fā)出信號(hào),就會(huì)判斷signal,signal2有沒有發(fā)出個(gè)信號(hào),有就會(huì)把最近發(fā)出的信號(hào)都包裝成元組發(fā)出。
控制臺(tái)輸出
2017-07-05 15:33:29.336 XXX[16308:202275] 信號(hào)釋放
2017-07-05 15:33:29.337 XXX[16308:202275] x == <RACTuple: 0x608000003460> (
1,
2
)
2017-07-05 15:33:29.337 XXX[16308:202275] 信號(hào)2釋放
3.5 combineLatest
將多個(gè)信號(hào)合并起來,并且拿到各個(gè)信號(hào)的最新的值,必須每個(gè)合并的signal至少都有過一次sendNext,才會(huì)觸發(fā)合并的信號(hào)。
RACSignal *combineSignal = [signal combineLatestWith:signal2];
[combineSignal subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
// 底層實(shí)現(xiàn):
// 1.當(dāng)組合信號(hào)被訂閱,內(nèi)部會(huì)自動(dòng)訂閱signal,signal2,必須兩個(gè)信號(hào)都發(fā)出內(nèi)容,才會(huì)被觸發(fā)。
// 2.并且把兩個(gè)信號(hào)組合成元組發(fā)出。
控制臺(tái)輸出 (和
zipWith
輸出一樣)
3.6 reduce
聚合:用于信號(hào)發(fā)出的內(nèi)容是元組,把信號(hào)發(fā)出元組的值聚合成一個(gè)值
// 聚合
// 常見的用法,(先組合在聚合)。combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock
// reduce中的block簡(jiǎn)介:
// reduceblcok中的參數(shù),有多少信號(hào)組合,reduceblcok就有多少參數(shù),每個(gè)參數(shù)就是之前信號(hào)發(fā)出的內(nèi)容
// reduceblcok的返回值:聚合信號(hào)之后的內(nèi)容。
RACSignal *reduceSignal = [RACSignal combineLatest:@[signal,signal2] reduce:^id (NSString *num1 ,NSString *num2){
return [NSString stringWithFormat:@"%@ -> %@",num1,num2];
}];
[reduceSignal subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
// 底層實(shí)現(xiàn):
// 1.訂閱聚合信號(hào),每次有內(nèi)容發(fā)出,就會(huì)執(zhí)行reduceblcok,把信號(hào)內(nèi)容轉(zhuǎn)換成reduceblcok返回的值。
控制臺(tái)輸出
2017-07-05 15:50:18.815 XXX[16553:210326] 信號(hào)釋放
2017-07-05 15:50:18.816 XXX[16553:210326] x == 1 -> 2
2017-07-05 15:50:18.816 XXX[16553:210326] 信號(hào)2釋放
四、ReactiveCocoa操作方法之秩序。
- doNext: 執(zhí)行Next之前,會(huì)先執(zhí)行這個(gè)Block
- doCompleted: 執(zhí)行sendCompleted之前,會(huì)先執(zhí)行這個(gè)Block
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信號(hào)釋放");
}];
}];
[[[signal doNext:^(id x) {
NSLog(@"執(zhí)行[subscriber sendNext:@\"1\"];之前會(huì)調(diào)用這個(gè)Block");
}] doCompleted:^{
NSLog(@"執(zhí)行[subscriber sendCompleted];之前會(huì)調(diào)用這個(gè)Block");
}] subscribeNext:^(id x) {
NSLog(@"x == %@",x);
}];
控制臺(tái)輸出
2017-07-05 15:58:44.053 XXX[16675:214218] 執(zhí)行[subscriber sendNext:@"1"];之前會(huì)調(diào)用這個(gè)Block
2017-07-05 15:58:44.054 XXX[16675:214218] x == 1
2017-07-05 15:58:44.055 XXX[16675:214218] 執(zhí)行[subscriber sendCompleted];之前會(huì)調(diào)用這個(gè)Block
2017-07-05 15:58:44.055 XXX[16675:214218] 信號(hào)釋放