本文在最快讓你上手ReactiveCocoa之基礎(chǔ)篇 此基礎(chǔ)上增加了部分自己見解,本文具體用作對ReactiveCocoa的歸納總結(jié),歡迎指導(dǎo)。
RACSignal:信號類,一般表示將來有數(shù)據(jù)傳遞,只要有數(shù)據(jù)改變,信號內(nèi)部接收到數(shù)據(jù),就會馬上發(fā)出數(shù)據(jù)
注意
- 信號類(RACSignal),只是表示當數(shù)據(jù)改變時,信號內(nèi)部會發(fā)出數(shù)據(jù),它本身不具備發(fā)送信號的能力,而是交給內(nèi)部一個訂閱者去發(fā)出。
- 默認一個信號都是冷信號,也就是值改變了,也不會觸發(fā),只有訂閱了這個信號,這個信號才會變?yōu)闊嵝盘?,值改變了才會觸發(fā)。
- 如何訂閱信號:調(diào)用信號RACSignal的subscribeNext就能訂閱。
常見的操作方法
- flattenMap map 用于把源信號內(nèi)容映射成新的內(nèi)容。
- concat 組合 按一定順序拼接信號,當多個信號發(fā)出的時候,有順序的接收信號
- then 用于連接兩個信號,當?shù)谝粋€信號完成,才會連接then返回的信號
- merge 把多個信號合并為一個信號,任何一個信號有新值的時候就會調(diào)用
- zipWith 把兩個信號壓縮成一個信號,只有當兩個信號同時發(fā)出信號內(nèi)容時,并且把兩個信號的內(nèi)容合并成一個元組,才會觸發(fā)壓縮流的next事件
- combineLatest 將多個信號合并起來,并且拿到各個信號的最新的值,必須每個合并的signal至少都有過一次sendNext,才會觸發(fā)合并的信號。
- reduce 聚合 用于信號發(fā)出的內(nèi)容是元組,把信號發(fā)出元組的值聚合成一個值
- filter 過濾信號,使用它可以獲取滿足條件的信號
- ignore 忽略完某些值的信號
- distinctUntilChanged 當上一次的值和當前的值有明顯的變化就會發(fā)出信號,否則會被忽略掉
- take 從開始一共取N次的信號
- takeLast 取最后N次的信號,前提條件,訂閱者必須調(diào)用完成,因為只有完成,就知道總共有多少信號
- takeUntil 獲取信號直到某個信號執(zhí)行完成
- skip 跳過幾個信號,不接受
- switchToLatest 用于signalOfSignals(信號的信號),有時候信號也會發(fā)出信號,會在signalOfSignals中,獲取signalOfSignals發(fā)送的最新信號
- doNext 執(zhí)行Next之前,會先執(zhí)行這個Block
- doCompleted 執(zhí)行sendCompleted之前,會先執(zhí)行這個Block
- timeout 超時,可以讓一個信號在一定的時間后,自動報錯。
- interval 定時 每隔一段時間發(fā)出信號
- delay 延遲發(fā)送next
- retry 重試 只要失敗,就會重新執(zhí)行創(chuàng)建信號中的block,直到成功
- replay 重放 當一個信號被多次訂閱,反復(fù)播放內(nèi)容
- throttle 節(jié)流 當某個信號發(fā)送比較頻繁時,可以使用節(jié)流,在某一段時間不發(fā)送信號內(nèi)容,過了一段時間獲取信號的最新內(nèi)容發(fā)出
使用步驟
1. 創(chuàng)建信號 createSignal
2. 訂閱信號,才會激活信號 subscribeNext
3. 發(fā)送信號 sendNext
底層實現(xiàn)
1. 創(chuàng)建信號,首先把didSubscribe保存到信號中,還不會觸發(fā)。
2. 當信號被訂閱,也就是調(diào)用signal的subscribeNext:nextBlock
2.1 subscribeNext內(nèi)部會調(diào)用signal的didSubscribe
2.2 subscribeNext內(nèi)部會創(chuàng)建訂閱者subscriber,并且把nextBlock保存到subscriber中
3.signal的didSubscribe中調(diào)用[subscriber sendNext:@1];
3.1 sendNext底層其實就是執(zhí)行subscriber的nextBlock
例子
// 1.創(chuàng)建信號
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// block調(diào)用時刻:每當有訂閱者訂閱信號,就會調(diào)用block。
// 3.發(fā)送信號
[subscriber sendNext:@"OrangeDeveloper"];
// 如果不在發(fā)送數(shù)據(jù),最好發(fā)送信號完成,內(nèi)部會自動調(diào)用[RACDisposable disposable]取消訂閱信號。
// 信號什么時候被取消:1.自動取消,當一個信號的訂閱者被銷毀的時候機會自動取消訂閱,2.手動取消
//除卻[subscriber sendCompleted];外還可在訂閱信號的時候返回一個RACDisposable,利用RACDisposable的disposable方法取消訂閱
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// 當信號發(fā)送完成或者發(fā)送錯誤,就會自動執(zhí)行這個block,取消訂閱信號。
// 執(zhí)行完Block后,當前信號就不在被訂閱了。
NSLog(@"信號被銷毀");
}];
}];
// 3.訂閱信號,才會激活信號.
[siganl subscribeNext:^(id x) {
// 每當有信號發(fā)出數(shù)據(jù),就會調(diào)用block.
NSLog(@"接收到數(shù)據(jù):%@",x);
}];
[siganl subscribeError:^(NSError *error) {
NSLog(@"訂閱錯誤信號");
}];
[siganl subscribeCompleted:^ {
NSLog(@"訂閱完成信號");
}];
RACSubscriber:表示訂閱者的意思,用于發(fā)送信號,這是一個協(xié)議,不是一個類,只要遵守這個協(xié)議,并且實現(xiàn)方法才能成為訂閱者。通過create創(chuàng)建的信號,都有一個訂閱者,幫助他發(fā)送數(shù)據(jù)
RACDisposable:用于取消訂閱或者清理資源,當信號發(fā)送完成或者發(fā)送錯誤的時候,就會自動觸發(fā)它
使用場景:不想監(jiān)聽某個信號時,可以通過它主動取消訂閱信號
- 當訂閱者發(fā)送信號sendNext之后,會執(zhí)行:subscribeNext中的nextBlock。當nextBlock執(zhí)行完畢也就意味著subscribeNext方法返回了RACDisposable對象
注意
- 如果不強引用訂閱者對象,默認情況下會自動取消訂閱,我們可以拿到RACDisposable 用disposableWithBlock做清空資源的一些操作了
- 如果不希望自動取消訂閱,我們應(yīng)該強引用RACSubscriber * subscriber。在想要取消訂閱的時候用subscribeNext返回的RACDisposable對象去調(diào)用dispose方法
RACSubject:信號提供者,自己可以充當信號,又能發(fā)送信號
使用場景:通常用來代替代理,有了它,就不必要定義代理了。
注意
RACSubject實例進行map操作之后, 發(fā)送完畢一定要調(diào)用sendCompleted, 否則會出現(xiàn)內(nèi)存泄漏; 而RACSignal實例不管是否進行map操作, 不管是否調(diào)用sendCompleted, 都不會出現(xiàn)內(nèi)存泄漏.
原因 : 因為RACSubject是熱信號, 為了保證未來有事件發(fā)生的時候, 訂閱者可以收到信息, 所以需要對持有訂閱者!
使用步驟
1.創(chuàng)建信號 [RACSubject subject],跟RACSiganl不一樣,創(chuàng)建信號時沒有block。
2.訂閱信號 subscribeNext
3.發(fā)送信號 sendNext
底層實現(xiàn)
1.調(diào)用subscribeNext訂閱信號,只是把訂閱者保存起來,并且訂閱者的nextBlock已經(jīng)賦值了
2.調(diào)用sendNext發(fā)送信號,遍歷剛剛保存的所有訂閱者,一個一個調(diào)用訂閱者的nextBlock
例子
// 1.創(chuàng)建信號
RACSubject *subject = [RACSubject subject];
// 2.訂閱信號
[subject subscribeNext:^(id x) {
// 當信號發(fā)出新值,就會調(diào)用.
NSLog(@"訂閱者%@",x);
}];
// 3.發(fā)送信號
[subject sendNext:@"OrangeDeveloper"];
RACSubject替換代理
需求:
- 給當前控制器添加一個按鈕,modal到另一個控制器界面
- 另一個控制器view中有個按鈕,點擊按鈕,通知當前控制器
步驟一:在第二個控制器.h,添加一個RACSubject代替代理。
@interface TwoViewController : UIViewController
@property (nonatomic, strong) RACSubject *delegateSignal;
@end
步驟二:監(jiān)聽第二個控制器按鈕點擊
@implementation TwoViewController
- (IBAction)notice:(id)sender {
// 通知第一個控制器,告訴它,按鈕被點了
// 通知代理
// 判斷代理信號是否有值
if (self.delegateSignal) {
// 有值,才需要通知
[self.delegateSignal sendNext:nil];
}
}
@end
步驟三:在第一個控制器中,監(jiān)聽跳轉(zhuǎn)按鈕,給第二個控制器的代理信號賦值,并且監(jiān)聽.
@implementation OneViewController
- (IBAction)btnClick:(id)sender {
// 創(chuàng)建第二個控制器
TwoViewController *twoVc = [[TwoViewController alloc] init];
// 設(shè)置代理信號
twoVc.delegateSignal = [RACSubject subject];
// 訂閱代理信號
[twoVc.delegateSignal subscribeNext:^(id x) {
NSLog(@"點擊了通知按鈕");
}];
// 跳轉(zhuǎn)到第二個控制器
[self presentViewController:twoVc animated:YES completion:nil];
}
@end
RACReplaySubject:重復(fù)提供信號類,RACSubject的子類
使用場景:
1.如果一個信號每被訂閱一次,就需要把之前的值重復(fù)發(fā)送一遍,使用重復(fù)提供信號類
2.可以設(shè)置capacity數(shù)量來限制緩存的value的數(shù)量,即只緩充最新的幾個值
使用步驟
1. 創(chuàng)建信號 [RACSubject subject],跟RACSignal不一樣,創(chuàng)建信號時沒有block
2. 可以先訂閱信號,也可以先發(fā)送信號
2.1 訂閱信號 subscribeNext
2.2 發(fā)送信號 sendNext
底層實現(xiàn)
1. 調(diào)用sendNext發(fā)送信號,把值保存起來,然后遍歷剛剛保存的所有訂閱者,一個一個調(diào)用訂閱者的nextBlock。
2. 調(diào)用subscribeNext訂閱信號,遍歷保存的所有值,一個一個調(diào)用訂閱者的nextBlock
(如果想當一個信號被訂閱,就重復(fù)播放之前所有值,需要先發(fā)送信號,再訂閱信號。即先保存值,再訂閱值)
例子
// 1.創(chuàng)建信號
RACReplaySubject *replaySubject = [RACReplaySubject subject];
// 2.發(fā)送信號
[replaySubject sendNext:@"OrangeDeveloper:1"];
[replaySubject sendNext:@"OrangeDeveloper:2"];
// 3.訂閱信號
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一個訂閱者接收到的數(shù)據(jù)%@",x);
}];
// 訂閱信號
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二個訂閱者接收到的數(shù)據(jù)%@",x);
}];
RACReplaySubject與RACSubject區(qū)別
RACReplaySubject可以先發(fā)送信號,在訂閱信號,RACSubject就不可以
RACTuple:元組類,類似NSArray,用來包裝值
RACSequence:RAC中的集合類,用于代替NSArray,NSDictionary,可以使用它來快速遍歷數(shù)組和字典 (貌似性能比較差不太推薦使用)
RACSequence和RACTuple簡單使用
// 1.遍歷數(shù)組
NSArray *numbers = @[@1,@2,@3,@4];
// 這里其實是三步
// 第一步: 把數(shù)組轉(zhuǎn)換成集合RACSequence numbers.rac_sequence
// 第二步: 把集合RACSequence轉(zhuǎn)換RACSignal信號類,numbers.rac_sequence.signal
// 第三步: 訂閱信號,激活信號,會自動把集合中的所有值,遍歷出來。
[numbers.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 2.遍歷字典,遍歷出來的鍵值對會包裝成RACTuple(元組對象)
NSDictionary *dict = @{@"name":@"OrangeDeveloper",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
// RACTupleUnpack 宏:專門用來解析元組
// RACTupleUnpack 括號里:需要解析的元組 宏的參數(shù),填解析的什么樣數(shù)據(jù)
// 元組里面有幾個值,宏的參數(shù)就必須填幾個
// 解包元組,會把元組的值,按順序給參數(shù)里面的變量賦值
RACTupleUnpack(NSString *key,NSString *value) = x;
// 相當于以下寫法
// NSString *key = x[0];
// NSString *value = x[1];
NSLog(@"%@ %@",key,value);
}];
// 3.字典轉(zhuǎn)模型
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
// 3.1 OC寫法
NSMutableArray *flags = [NSMutableArray array];
for (NSDictionary *dict in dictArr) {
FlagItem *item = [FlagItem flagWithDict:dict];
[flags addObject:item];
}
// 3.2 RAC寫法
NSMutableArray *flags = [NSMutableArray array];
_flags = flags;
// rac_sequence注意點:調(diào)用subscribeNext,并不會馬上執(zhí)行nextBlock,而是會等一會。
[dictArr.rac_sequence.signal subscribeNext:^(id x) {
// 運用RAC遍歷字典,x:字典
FlagItem *item = [FlagItem flagWithDict:x];
[flags addObject:item];
}];
// 3.3 RAC高級寫法:
// map:映射的意思,目的:把原始值value映射成一個新值
// array: 把集合轉(zhuǎn)換成數(shù)組
// 底層實現(xiàn):當信號被訂閱,會遍歷集合中的原始值,映射成新值,并且保存到新的數(shù)組里。
NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {
return [FlagItem flagWithDict:value];
}] array];
RACCommand:RAC中用于處理事件的類,可以把事件如何處理,事件中的數(shù)據(jù)如何傳遞,包裝到這個類中,他可以很方便的監(jiān)控事件的執(zhí)行過程
使用場景:監(jiān)聽按鈕點擊,網(wǎng)絡(luò)請求
使用步驟
1. 創(chuàng)建命令 initWithSignalBlock
2. 在signalBlock中,創(chuàng)建RACSignal,并且作為signalBlock的返回值
3. 執(zhí)行命令 execute
注意
1. signalBlock必須要返回一個信號,不能傳nil.
2. 如果不想要傳遞信號,直接創(chuàng)建空的信號[RACSignal empty];
3. RACCommand中信號如果數(shù)據(jù)傳遞完,必須調(diào)用[subscriber sendCompleted],這時命令才會執(zhí)行完畢,否則永遠處于執(zhí)行中。
4. RACCommand需要被強引用,否則接收不到RACCommand中的信號,因此RACCommand中的信號是延遲發(fā)送的。
設(shè)計思想:內(nèi)部signalBlock為什么要返回一個信號,這個信號有什么用
1. 在RAC開發(fā)中,通常會把網(wǎng)絡(luò)請求封裝到RACCommand,直接執(zhí)行某個RACCommand就能發(fā)送請求。
2. 當RACCommand內(nèi)部請求到數(shù)據(jù)的時候,需要把請求的數(shù)據(jù)傳遞給外界,這時候就需要通過signalBlock返回的信號傳遞了。
如何拿到RACCommand中返回信號發(fā)出的數(shù)據(jù)
1. RACCommand有個執(zhí)行信號源executionSignals,這個是signal of signals(信號的信號),意思是信號發(fā)出的數(shù)據(jù)是信號,不是普通的類型。
2. 訂閱executionSignals就能拿到RACCommand中返回的信號,然后訂閱signalBlock返回的信號,就能獲取發(fā)出的值。
例子
// 1.創(chuàng)建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// 創(chuàng)建空信號,必須返回信號 不允許為nil return [RACSignal empty];
// 2.創(chuàng)建信號,用來傳遞數(shù)據(jù)
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"請求數(shù)據(jù)"];
// 注意:數(shù)據(jù)傳遞完,最好調(diào)用sendCompleted,這時命令才執(zhí)行完畢。
[subscriber sendCompleted];
return nil;
}];
}];
// 強引用命令,不要被銷毀,否則接收不到數(shù)據(jù)
_conmmand = command;
// 3.訂閱RACCommand中的信號
[command.executionSignals subscribeNext:^(id x) {
[x subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}];
// RAC高級用法
// switchToLatest:用于signal of signals,獲取signal of signals發(fā)出的最新信號,也就是可以直接拿到RACCommand中的信號
// switchToLatest獲取最新發(fā)送的信號,只能用于信號中信號。
[command.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 4.監(jiān)聽命令是否執(zhí)行完畢
// executing 一開始就會監(jiān)聽一次,肯定是 0,一般會忽略(skip)一次
// x 非 0 即 1,命令執(zhí)行完畢/正在執(zhí)行
// 執(zhí)行一次命令,block 中會調(diào)用兩次,正在執(zhí)行->執(zhí)行完畢
[[command.executing skip:1] subscribeNext:^(id x) {
if ([x boolValue] == YES) {
// 正在執(zhí)行
NSLog(@"正在執(zhí)行");
}else{
// 執(zhí)行完成
NSLog(@"執(zhí)行完成");
}
}];
// 5.執(zhí)行命令
[self.conmmand execute:@"OrangeDeveloper"];
RACMulticastConnection:用于當一個信號,被多次訂閱時,為了保證創(chuàng)建信號時,避免多次調(diào)用創(chuàng)建信號中的block,造成副作用,可以使用這個類處理
注意
RACMulticastConnection通過RACSignal的publish或者muticast方法創(chuàng)建
使用步驟
1. 創(chuàng)建信號 createSignal
2. 創(chuàng)建連接 RACMulticastConnection *connect = [signal publish];
3. 訂閱信號,注意:訂閱的不在是之前的信號,而是連接的信號。 [connect.signal subscribeNext:nextBlock]
4. 連接 [connect connect]
底層原理
1. 創(chuàng)建connect,connect.sourceSignal -> RACSignal(原始信號) connect.signal -> RACSubject
2. 訂閱connect.signal,會調(diào)用RACSubject的subscribeNext,創(chuàng)建訂閱者,而且把訂閱者保存起來,不會執(zhí)行block
3. [connect connect]內(nèi)部會訂閱RACSignal(原始信號),并且訂閱者是RACSubject
3.1 訂閱原始信號,就會調(diào)用原始信號中的didSubscribe
3.2 didSubscribe,拿到訂閱者調(diào)用sendNext,其實是調(diào)用RACSubject的sendNext
4. RACSubject的sendNext,會遍歷RACSubject所有訂閱者發(fā)送信號
4.1 因為剛剛第二步,都是在訂閱RACSubject,因此會拿到第二步所有的訂閱者,調(diào)用他們的nextBlock
例子
- 需求:假設(shè)在一個信號中發(fā)送請求,每次訂閱一次都會發(fā)送請求,這樣就會導(dǎo)致多次請求
- 解決:使用RACMulticastConnection就能解決
// 1.創(chuàng)建請求信號 // 普通寫法, 這樣的缺點是:沒訂閱一次信號就得重新創(chuàng)建并發(fā)送請求,這樣很不友好
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// didSubscribeblock中的代碼都統(tǒng)稱為副作用。
// 發(fā)送請求---比如afn
NSLog(@"發(fā)送請求");
return nil;
}];
// 2.訂閱信號
[signal subscribeNext:^(id x) {
NSLog(@"接收數(shù)據(jù)");
}];
// 2.訂閱信號
[signal subscribeNext:^(id x) {
NSLog(@"接收數(shù)據(jù)");
}];
// 3.運行結(jié)果,會執(zhí)行兩遍發(fā)送請求,也就是每次訂閱都會發(fā)送一次請求
// RACMulticastConnection:解決重復(fù)請求問題 比較好的做法。 使用RACMulticastConnection,無論有多少個訂閱者,無論訂閱多少次,我只發(fā)送一個。
// 1.創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"發(fā)送請求");
[subscriber sendNext:@"OrangeDeveloper"];
return nil;
}];
// 2.創(chuàng)建連接
RACMulticastConnection *connect = [signal publish];
// 3.訂閱信號,
// 注意:訂閱信號,也不能激活信號,只是保存訂閱者到數(shù)組,必須通過連接,當調(diào)用連接,就會一次性調(diào)用所有訂閱者的sendNext:
[connect.signal subscribeNext:^(id x) {
NSLog(@"訂閱者一信號");
}];
[connect.signal subscribeNext:^(id x) {
NSLog(@"訂閱者二信號");
}];
// 4.連接,激活信號
[connect connect];
RACScheduler:RAC中的隊列,用GCD封裝的
RACUnit :表?stream不包含有意義的值,也就是看到這個,可以直接理解為nil
RACEvent: 把數(shù)據(jù)包裝成信號事件(signal event)。它主要通過RACSignal的materialize來使用,然并卵
開發(fā)中常見用法
rac_signalForSelector:用于替代代理
rac_valuesAndChangesForKeyPath:用于監(jiān)聽某個對象的屬性改變
rac_signalForControlEvents:用于監(jiān)聽某個事件
rac_addObserverForName:用于監(jiān)聽某個通知
rac_textSignal:只要文本框發(fā)出改變就會發(fā)出這個信號
rac_liftSelector:withSignalsFromArray:Signals:當傳入的Signals(信號數(shù)組),每一個signal都至少sendNext過一次,就會去觸發(fā)第一個selector參數(shù)的方法
例子
// 1.代替代理
// 需求:自定義redView,監(jiān)聽紅色view中按鈕點擊
// 之前都是需要通過代理監(jiān)聽,給紅色View添加一個代理屬性,點擊按鈕的時候,通知代理做事情
// rac_signalForSelector:把調(diào)用某個對象的方法的信息轉(zhuǎn)換成信號,就要調(diào)用這個方法,就會發(fā)送信號。
// 這里表示只要redV調(diào)用btnClick:,就會發(fā)出信號,訂閱就好了。
[[redV rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
NSLog(@"點擊紅色按鈕");
}];
// 2.KVO
// 把監(jiān)聽redV的center屬性改變轉(zhuǎn)換成信號,只要值改變就會發(fā)送信號
// observer:可以傳入nil
[[redV rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 3.監(jiān)聽事件
// 把按鈕點擊事件轉(zhuǎn)換為信號,點擊按鈕,就會發(fā)送信號
[[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
NSLog(@"按鈕被點擊了");
}];
// 4.代替通知
// 把監(jiān)聽到的通知轉(zhuǎn)換信號
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
NSLog(@"鍵盤彈出");
}];
// 5.監(jiān)聽文本框的文字改變
[_textField.rac_textSignal subscribeNext:^(id x) {
NSLog(@"文字改變了%@",x);
}];
// 6.處理多個請求,都返回結(jié)果的時候,統(tǒng)一做處理.
RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 發(fā)送請求1
[subscriber sendNext:@"發(fā)送請求1"];
return nil;
}];
RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 發(fā)送請求2
[subscriber sendNext:@"發(fā)送請求2"];
return nil;
}];
// 使用注意:幾個信號,參數(shù)一的方法就幾個參數(shù),每個參數(shù)對應(yīng)信號發(fā)出的數(shù)據(jù)。
[self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];
}
// 更新UI
- (void)updateUIWithR1:(id)data r2:(id)data1
{
NSLog(@"更新UI%@ %@",data,data1);
}
常見宏
RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于給某個對象的某個屬性綁定。 把一個對象的某個屬性綁定一個信號,只要發(fā)出信號,就會把信號的內(nèi)容給對象的屬性賦值
// 只要文本框文字改變,就會修改label的文字
RAC(self.labelView,text) = _textField.rac_textSignal;
RACObserve(self, name):監(jiān)聽某個對象的某個屬性,返回的是信號
//例 textField輸入的值賦值給label,監(jiān)聽label文字改變,
RAC(self.label, text) = self.textField.rac_textSignal;
[RACObserve(self.label, text) subscribeNext:^(id x) {
NSLog(@"====label的文字變了");
}];
@weakify(Obj)和@strongify(Obj),一般兩個都是配套使用,在主頭文件(ReactiveCocoa.h)中并沒有導(dǎo)入,需要自己手動導(dǎo)入,RACEXTScope.h才可以使用。但是每次導(dǎo)入都非常麻煩,只需要在主頭文件自己導(dǎo)入就好了
注意
/**
* 循環(huán)引用問題
*/
@weakify(self)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
@strongify(self)
NSLog(@"%@",self.view);
return nil;
}];
_signal = signal;
使用 @weakify(self)和@strongify(self)來避免循環(huán)引用
RACTuplePack:把數(shù)據(jù)包裝成RACTuple(元組類)
// 把參數(shù)中的數(shù)據(jù)包裝成元組
RACTuple *tuple = RACTuplePack(@10,@20);
RACTupleUnpack:把RACTuple(元組類)解包成對應(yīng)的數(shù)據(jù)
// 把參數(shù)中的數(shù)據(jù)包裝成元組
RACTuple *tuple = RACTuplePack(@"OrangeDeveloper",@18);
// 解包元組,會把元組的值,按順序給參數(shù)里面的變量賦值
// name = @"OrangeDeveloper" age = @18
RACTupleUnpack(NSString *name,NSNumber *age) = tuple;