序
之前就一直在看ReactiveCocoa 相關知識 但是有感覺每次看完收貨甚微靴庆,且感覺零零散散 颁独,本blog 僅僅是記錄自己的學習過程
文章目錄
- 1 ReactiveCocoa 介紹
- 2 ReactiveCocoa的應用場景
- 3 ReactiveCocoa 被描述為函數(shù)式響應編程(FRP)框架
- 4 如何添加ReactiveCocoa
- 5 分析ReactiveCocoa中的常見類
- 5-1 RACSignal:信號類
- 5-2 RACSubscriber:訂閱者
- 5-3 RACDisposable:取消訂閱
- 5-4 RACSubject:信號提供者可發(fā)信號可充當信號
- 5-5 RACTuple:元祖類 類似NSArray用來包裝值
- 5-6 RACSequence (Sequence:序列排序) :RAC中的集合類 用于代替NSArray 和 NSDictionary 可以使用它來快速遍歷數(shù)組和字典
- 5-7 RACCommand :RAC中用于處理事件的類, 可以吧事件如何處理,事件中的數(shù)據(jù)如何傳遞矮锈,包裝到這個類中 他可以很方便的監(jiān)控事件的執(zhí)行過程
- 5-8 RACMulticastConnection 用于當一個信號被多次訂閱是為了保證創(chuàng)建信號時 避免多次調用創(chuàng)建信號中的block 造成副作用 可以使用這個類創(chuàng)建
- 5-9 RACScheduler :RAC中的隊列 用GCD封裝的
- 5-10 RACUnit :表示Stream不包含有意義的值 也就是看到這個 可以直接理解為nil
- 6 ReactiveCocoa 開發(fā)中常見的用法
- 6-1 代替代理
- 6-2 代替KVO
- 6-3 監(jiān)聽事件
- 6-4 代替通知
- 6-5 監(jiān)聽文本框文字的改變
- 6-6 處理多個請求 都返回結果的時候統(tǒng)一做處理
- 6-7 定時器
- 7 ReactiveCocoa 開發(fā)中常見的用法
- 7-1 RAC(TARGET, ...) 用于給某個對象的某個屬性綁定
- 7-2 RACObserve(TARGET, KEYPATH) 監(jiān)聽某個對象的某個屬性 返回的是信號
- 7-3 RACTuplePack 把數(shù)據(jù)包裝成RACTuple (元祖類) RACTupleUnpack 把元祖解包成對應的數(shù)據(jù)
1 ReactiveCocoa 介紹
ReactiveCocoa(其簡稱為RAC)是由Github 開源的一個應用于iOS和OS X開發(fā)的新框架。RAC具有函數(shù)式編程和響應式編程的特性
2 ReactiveCocoa的應用場景
對于一個應用來說睁蕾,絕大部分的時間都是在等待某些事件的發(fā)生或響應某些狀態(tài)的變化苞笨,比如用戶的觸摸事件、應用進入后臺子眶、網(wǎng)絡請求成功刷新界面等等猫缭,而維護這些狀態(tài)的變化,常常會使代碼變得非常復雜壹店,難以擴展猜丹。而 ReactiveCocoa 給出了一種非常好的解決方案,它使用信號來代表這些異步事件硅卢,提供了一種統(tǒng)一的方式來處理所有異步的行為射窒,包括代理方法、block 回調将塑、target-action 機制脉顿、通知、KVO 等
3 ReactiveCocoa 被描述為函數(shù)式響應編程(FRP)框架
ReactiveCocoa結合了幾種編程風格
函數(shù)式編程(Functional Programming)
是把操作盡量寫成一系列嵌套的函數(shù)或者方法調用点寥。
函數(shù)式編程特點:每個方法必須有返回值(本身對象),把函數(shù)或者Block當做參數(shù),block參數(shù)(需要操作的值)block返回值(操作結果)
代表: ReactiveCocoa
響應式編程(Reactive Programming )
不需要考慮調用順序艾疟,只需要知道考慮結果,類似于蝴蝶效應敢辩,產(chǎn)生一個事件蔽莱,會影響很多東西,這些事件像流一樣的傳播出去戚长,然后影響結果盗冷,借用面向對象的一句話,萬物皆是流同廉。
代表:KVO運用
鏈式編程
是將多個操作(多行代碼)通過點號(.)鏈接在一起成為一句代碼,使代碼可讀性好仪糖。a(1).b(2).c(3)
鏈式編程特點:方法的返回值是block,block必須有返回值(本身對象),block參數(shù)(需要操作的值)
代表作 Masonry
4 添加ReactiveCocoa到項目中
使用cocoapods
具體電腦配置cocoapods
網(wǎng)上資料一大堆 我就不多說了 自行Google
pod 'ReactiveCocoa', '~> 2.5'
5 分析ReactiveCocoa的中的常見類
仔細看了源碼 發(fā)現(xiàn) RAC中最核心的類是RACSignal迫肖, 好了 接下來就是研究RACSignal了
5-1 RACSignal:信號類
一般表示將來有數(shù)據(jù)傳遞 只要有數(shù)據(jù)改變信號內部接受到數(shù)據(jù) 就會馬上發(fā)出數(shù)據(jù)
注意:
RACSignal(信號類) 只是表示數(shù)據(jù)改變時 信號內部會發(fā)出數(shù)據(jù) 它本身不具備發(fā)送信號的能力 而是交給內部一個訂閱者去發(fā)出(下文會講到RACSubject類 有區(qū)別)
默然信號都是冷信號 也就是值改變了也不會觸發(fā) 只有訂閱了這個信號 這個信號才是熱信號 值改變了才會觸發(fā)
訂閱信號:調用信號RACSignal的subscribeNext就能訂閱
RACSignal的簡單使用:
// 1 創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 2 發(fā)送信號
[subscriber sendNext:@"123"];
// 如果不發(fā)送數(shù)據(jù) 最好發(fā)送信號完成 內部會自動調用[RACDisposable disposable]取消訂閱信號锅劝。
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
//block調用時刻:當信號發(fā)送完成或者發(fā)送錯誤,就會自動執(zhí)行這個block,取消訂閱信號蟆湖。
// 執(zhí)行完Block后故爵,當前信號就不在被訂閱了。
NSLog(@"信號被銷毀了");
}];
}];
// 3 訂閱信號
[signal subscribeNext:^(id x) {
// block 調用時刻 每當有信號發(fā)出數(shù)據(jù) 就會調用block帐姻;
NSLog(@"接收到數(shù)據(jù)%@",x);
}];
- RACSignal的底層實現(xiàn)原理
- 1.創(chuàng)建信號稠集,首先把didSubscribe保存到信號中奶段,還不會觸發(fā)。
- 2.當信號被訂閱剥纷,也就是調用signal subscribeNext:nextBlock
- 2.2 subscribeNext內部會創(chuàng)建訂閱者subscriber痹籍,并且把nextBlock保存到subscriber中。
- 2.1 subscribeNext內部會調用siganl的didSubscribe
- 3.siganl的didSubscribe中調用[subscriber sendNext:@1];
- 3.1 sendNext底層其實就是執(zhí)行subscriber的nextBlock
5-2 RACSubscriber
表示訂閱者的意思 用于發(fā)送信號 這是一個協(xié)議 不是一個類 只要遵守這個協(xié)議 并且實現(xiàn)方法才能成為訂閱者 通過create創(chuàng)建的信號都有一個訂閱者 幫助他發(fā)送數(shù)據(jù)
5-3 RACDisposable
用于取消訂閱或者清理資源 當信號發(fā)送完成或者發(fā)送錯誤的時候 就會自動觸發(fā)他
- 不想監(jiān)聽某個信號時 可以通過它主動取消訂閱信號
5-4 RACSubject
信號提供者 自己可以充當信號 又能發(fā)送信號
- 通常用來代替代理 有了它 就不必要定義代理了
RACReplySubject 重復提供信號類 晦鞋,RACSubject的子類
RACReplySubject 和RACSubject區(qū)別
RACReplySubject 可以先發(fā)送信號再訂閱信號蹲缠, RACSubject就不可以
使用場景1 :如果一個信號每被訂閱一次 就需要把之前的值重復發(fā)送一遍 使用重復提供信號類
使用場景2 :可以設置capacity數(shù)量來限制緩存的value的數(shù)量 即只緩存最新的幾個值
RACSubject 的簡單實用
// 1 創(chuàng)建信號
RACSubject *subject = [RACSubject subject];
// 2 訂閱信號
[subject subscribeNext:^(id x) {
NSLog(@"第一個訂閱者 %@",x);
}];
[subject subscribeNext:^(id x) {
NSLog(@"第二個訂閱者 %@",x);
}];
// 3 發(fā)送信號
[subject sendNext:@123];
- RACSubject的底層實現(xiàn)原理
- RACSubject底層實現(xiàn) 和RACSignal不一樣
- 1 調用SubjectNext 訂閱信號 只是把訂閱者保存起來 并且訂閱者的nextBlock已經(jīng)賦值了
- 2 調用sendNext 發(fā)送信號遍歷剛剛保存的訂閱者 一個一個調用訂閱者的nextBlock
RACReplaySubject 的簡單使用
// 1 創(chuàng)建信號
RACReplaySubject *replySubject = [RACReplaySubject subject];
// 2 發(fā)送信號
[replySubject sendNext:@"我是ReplySubject -- 1"];
[replySubject sendNext:@"我是ReplySubject -- 2"];
// 3 訂閱信號
[replySubject subscribeNext:^(id x) {
NSLog(@"第一個訂閱者接收到的數(shù)據(jù)%@",x);
}];
[replySubject subscribeNext:^(id x) {
NSLog(@"第二個訂閱者接收到的數(shù)據(jù)%@",x);
}];
// 下邊是打印結果
第一個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 1
第一個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 2
第二個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 1
第二個訂閱者接收到的數(shù)據(jù)我是ReplySubject -- 2
-
RACReplySubject的底層實現(xiàn)原理
- RACReplaySubject:底層實現(xiàn)和RACSubject不一樣。
- 1.調用sendNext發(fā)送信號悠垛,把值保存起來线定,然后遍歷剛剛保存的所有訂閱者,一個一個調用訂閱者的nextBlock确买。
- 2.調用subscribeNext訂閱信號斤讥,遍歷保存的所有值,一個一個調用訂閱者的nextBlock
- 如果想當一個信號被訂閱湾趾,就重復播放之前所有值芭商,需要先發(fā)送信號,在訂閱信號搀缠。 也就是先保存值铛楣,在訂閱值。
- RACSubject 的項目中的使用 替換代理
// 在第一個控制器里邊 我用的是脫線跳轉 所有在此方法中獲取控制器 實例化subject 然后訂閱信號
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailViewController *detailVC = segue.destinationViewController;
// 實例化
detailVC.delagateSignal = [RACSubject subject];
// 訂閱信號
[detailVC.delagateSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
// 在DetailViewController.h 中添加屬性
@property(nonatomic, strong)RACSubject *delagateSignal;
// 在DetailViewController.m 中的點擊方法中 判斷 delagateSignal 是否實例話 然后發(fā)送信號
- (IBAction)delegateBtn:(id)sender {
if (self.delagateSignal) {
// 發(fā)送信號
[self.delagateSignal sendNext:@"我是從詳情里邊出來的哈哈"];
}
}
5-5 RACTuple:元祖類 類似NSArray 用來包裝值
5-6 RACSequence (Sequence:序列排序) :RAC中的集合類 用于代替NSArray 和 NSDictionary 可以使用它來快速遍歷數(shù)組和字典
- 簡單使用 遍歷數(shù)組 和遍歷字典
// 1 遍歷數(shù)組
NSArray *arr = @[@1,@2,@3,@4,@5];
[arr.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 2 遍歷字典
// 2 遍歷字典
NSDictionary *dict = @{@"name":@"奧卡姆剃須刀",
@"age":@"25",
@"location":@"beijing"
};
[dict.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
此處打印出來的鍵值會被包裝為RACTuple元祖類型 以下為打印結果
Reactive Demo[9312:370525] <RACTuple: 0x608000004790> (
location,
beijing
)
// 所以遍歷字典時候 應該將id直接改為RACTuple
[dict.rac_sequence.signal subscribeNext:^(RACTuple * x) {
// 解包元祖 會把元祖的值 按順序給參數(shù)里邊的變量賦值
RACTupleUnpack(NSString *key,NSString *value) = x;
NSLog(@"%@----%@",key,value);
}];
// 打印結果
name----奧卡姆剃須刀
age----25
location----beijing
- 實現(xiàn)字典轉模型
// OC寫法
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"PeopleList.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
NSMutableArray *modelArr = [NSMutableArray arrayWithCapacity:dictArr.count];
for (NSDictionary *dict in dictArr) {
PeopleModel *model = [PeopleModel peopleWithDict:dict];
[modelArr addObject:model];
}
// RAC 寫法
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"PeopleList.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
NSMutableArray *modelArr = [NSMutableArray arrayWithCapacity:dictArr.count];
// RACSequence 調用subcribeNext 并不會馬上執(zhí)行NextBlock 而是要等一會 可以在下方添加一個nslog 會現(xiàn)在log
[dictArr.rac_sequence.signal subscribeNext:^(id x) {
PeopleModel *model = [PeopleModel peopleWithDict:x];
[modelArr addObject:model];
}];
NSLog(@"奧卡姆剃須刀");
// RAC高級寫法
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"PeopleList.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
NSArray *modelArr = [[dictArr.rac_sequence map:^id(id value) {
return [PeopleModel peopleWithDict:value];
}]array];
NSLog(@"%@",modelArr);
// map: 映射的意思 把原始的值value映射成一個新值 形成一個新的集合 RACDynamicSequence
// array 把RACDynamicSequence集合準換成我們熟知的數(shù)組
// 底層實現(xiàn) 當信號被訂閱是 會遍歷集合中的原始值 映射成新值 并且保存到新的RACDynamicSequence集合中
5-7 RACCommand :RAC中用于處理事件的類艺普, 可以吧事件如何處理簸州,事件中的數(shù)據(jù)如何傳遞,包裝到這個類中 他可以很方便的監(jiān)控事件的執(zhí)行過程
- 監(jiān)聽按鈕的點擊歧譬,網(wǎng)絡請求 簡單實用
// RACCommand使用步驟
// 1 創(chuàng)建命令
// 2 在signalBlock中 創(chuàng)建信號signal 作為signalblock的返回
// 3 執(zhí)行命令 execute
// 1 創(chuàng)建命令
RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal *(id input) {
NSLog(@"執(zhí)行命令%@",input);
// 2 創(chuàng)建信號 用來傳遞數(shù)據(jù)
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 在這里邊發(fā)送網(wǎng)絡請求 然后將請求道的結果數(shù)據(jù)返回給外界
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"我是數(shù)據(jù)"];
// 發(fā)送信號完成后 要發(fā)送完成
[subscriber sendCompleted];
});
return nil;
}];
}];
// 3 訂閱RACCommand的信號 在此處可以拿到網(wǎng)絡請求回來的數(shù)據(jù)
[command.executionSignals subscribeNext:^(id x) {
[x subscribeNext:^(id x) {
NSLog(@"----%@",x);
}];
}];
// RAC 的高級用法
//switchToLatest 用于signal of signals 獲取 signal of signals 發(fā)出的最新信號也就是可以直接拿到RACCommand中的信號
[command.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"switchToLatest---%@",x);
}];
// 4 監(jiān)聽命令是否執(zhí)行完畢 默認會來一次 可以直接跳過 skip表示跳過信號
[[command.executing skip:1] subscribeNext:^(id x) {
if ([x boolValue] == YES) {
NSLog(@"正在執(zhí)行");
}else{
NSLog(@"執(zhí)行完畢");
}
}];
// 5 執(zhí)行命令 執(zhí)行命令的時候 會調用command的block 訂閱信號時 block中的信號才能發(fā)送出去
[command execute:@1];
-
RACCommand 使用注意
- 1 signalBlock 必須返回一個信號 不能返回nil 不過可以傳一個空信號 [RACSignal empty];
- 2 RACCommand 中信號如果數(shù)據(jù)傳遞完 必須調用 [subscriber sendCompleted];這是命令才會執(zhí)行完畢 否則一直在執(zhí)行過程中
- 3 comman 需要強引用
-
RACCommand的設計思想 signalBlock內部為什么要返回一個信號 這個信號有什么用呢
- 1 在RAC開發(fā)中 通常會把網(wǎng)絡請求封裝在RACCommand 直接執(zhí)行某個command就能發(fā)送請求
- 2 在RACCommand內部請求道數(shù)據(jù)的時候 需要把請求的數(shù)據(jù)傳遞給外界這時候就需要signalblock返回的信號傳遞了
-
如何拿到command中返回信號發(fā)出的數(shù)據(jù)
- 1 RACCommand 有一個執(zhí)行信號源executionSignals 這個是signal of signals(信號的信號),意思是信號發(fā)出的數(shù)據(jù)是信號慌植,不是普通的類型尸红。
- 2 訂閱executionSignals 就能拿到RACCommand中返回的信號 然后訂閱signalblock返回的信號 就能獲取發(fā)出的值
監(jiān)聽當前命令是否正在執(zhí)行executing
使用場景 監(jiān)聽按鈕的點擊 網(wǎng)絡請求
5-8 RACMulticastConnection 用于當一個信號被多次訂閱是為了保證創(chuàng)建信號時 避免多次調用創(chuàng)建信號中的block 造成副作用 可以使用這個類創(chuàng)建
- RACMulticastConnection 通過RACSignal 的publish或者muticast:方法創(chuàng)建
// 來先看一個例子
// 需求:假設在一個信號中發(fā)送請求巩步,每次訂閱一次都會發(fā)送請求宋距,這樣就會導致多次請求率拒。
// 解決:使用RACMulticastConnection就能解決.
// 看一下錯誤的例子
// 1 創(chuàng)建請求信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"發(fā)送請求");
[subscriber sendNext:@1];
return nil;
}];
// 2 訂閱信號
[signal subscribeNext:^(id x) {
NSLog(@"接受數(shù)據(jù)1");
}];
// 3 再次訂閱信號
[signal subscribeNext:^(id x) {
NSLog(@"接收數(shù)據(jù)2");
}];
// 4 運行結果 會執(zhí)行兩遍發(fā)送請求 也就是每次訂閱都會發(fā)送一次請求
// 下邊是使用RACMulticastConnection 能夠解決發(fā)送兩次請求的問題
// RACMulticastConnection 解決重復請求的問題
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"發(fā)送請求");
[subscriber sendNext:@1];
return nil;
}];
// 2 創(chuàng)建鏈接
RACMulticastConnection *connect = [signal publish];
// 3 訂閱信號
[connect.signal subscribeNext:^(id x) {
NSLog(@"接受數(shù)據(jù) 1 --%@",x);
}];
[connect.signal subscribeNext:^(id x) {
NSLog(@"接受數(shù)據(jù) 2 -- %@",x);
}];
// 4 鏈接 激活信號
[connect connect];
RACMulticastConnection底層原理:
1.創(chuàng)建connect叶撒,connect.sourceSignal -> RACSignal(原始信號) connect.signal -> RACSubject
2.訂閱connect.signal垫毙,會調用RACSubject的subscribeNext河咽,創(chuàng)建訂閱者蛆橡,而且把訂閱者保存起來舌界,不會執(zhí)行block。
3.[connect connect]內部會訂閱RACSignal(原始信號)泰演,并且訂閱者是RACSubject
3.1.訂閱原始信號呻拌,就會調用原始信號中的didSubscribe
3.2 didSubscribe,拿到訂閱者調用sendNext睦焕,其實是調用RACSubject的sendNext
4.RACSubject的sendNext,會遍歷RACSubject所有訂閱者發(fā)送信號藐握。
4.1 因為剛剛第二步靴拱,都是在訂閱RACSubject,因此會拿到第二步所有的訂閱者猾普,調用他們的nextBlock
5-9 RACScheduler :RAC中的隊列 用GCD封裝的
5-10 RACUnit :表示Stream不包含有意義的值 也就是看到這個 可以直接理解為nil
6 ReactiveCocoa 開發(fā)中常見的用法
6-1 代替代理
- 個人感覺這個方法代替代理并沒有省多少代碼 類似于block 代碼相對集中了而已
// 代替代理
// 主控制器中的代碼
CustomView *V = [[CustomView alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];
V.backgroundColor = [UIColor redColor];
[self.view addSubview:V];
V.delegate = self;
[[V rac_signalForSelector:@selector(TapClick)] subscribeNext:^(id x) {
NSLog(@"點擊了視圖中的按鈕%@",x);
}];
// CustomView 中的代碼 和之前遵守協(xié)議設置代理代理實現(xiàn)方法是一樣一樣的
.h
@protocol CustomViewDelagate <NSObject>
- (void)CustomViewTapClick;
@end
@interface CustomView : UIView
@property (nonatomic,weak) id<CustomViewDelagate> delegate;
@end
.m
- (void)TapClick{
if ([self.delegate respondsToSelector:@selector(CustomViewTapClick)]) {
[self.delegate CustomViewTapClick];
}
}
6-2 代替KVO
- 使用RAC代替KVO很簡單,一句話就可以搞定,而且相比傳統(tǒng)的KVO,不僅代碼不用放在一起寫美觀了很多,同時還能達到高聚合低耦合的目標
//第一種方式 代替KVO
[RACObserve(scrollView, contentOffset) subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 第二種方式
// 2.KVO
// 把監(jiān)聽redV的center屬性改變轉換成信號袜炕,只要值改變就會發(fā)送信號
// observer:可以傳入nil
[[redV rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
6-3 監(jiān)聽事件
- rac_signalForControlEvents 同樣簡單,一句話搞定
// 監(jiān)聽事件
[[self.signalBtn rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(id x) {
// 傳遞的btn
NSLog(@"點擊了按鈕%@",x);
}];
6-4 代替通知
// 正確的寫法--1 這個寫法 當dealloc信號發(fā)出的時候 就釋放通知
[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {
NSLog(@"鍵盤彈出");
}];
// 正確的寫法--2 自己創(chuàng)建一個要釋放的信號
RACSignal *deallocSignal = [self rac_signalForSelector:@selector(viewWillDisappear:)];
[[[[NSNotificationCenter defaultCenter]rac_addObserverForName:UIKeyboardWillShowNotification object:nil] takeUntil:deallocSignal] subscribeNext:^(id x) {
NSLog(@"鍵盤彈出%@",x);
}];
// 這是個錯誤的示范
這個寫法有個問題,這樣子寫信號不會被釋放,當你再次收到鍵盤彈出的通知時他會疊加上次的信號進行執(zhí)行,并一直疊加下去,所以我們在用上面的寫法
[[[NSNotificationCenter defaultCenter]rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
6-5 監(jiān)聽文本框文字的改變
[self.textFiled.rac_textSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
6-6 處理多個請求 都返回結果的時候統(tǒng)一做處理
- (void)moreRequest{
RACSignal *request1 = [RACSignal
createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"我是數(shù)據(jù) - 1"];
[subscriber sendCompleted];
});
return nil;
}];
RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"我是數(shù)據(jù) - 2"];
[subscriber sendCompleted];
});
return nil;
}];
// 前邊的方法參數(shù)和后邊信號的數(shù)據(jù)是一一對應的
[self rac_liftSelector:@selector(reloadData1:Data2:) withSignalsFromArray:@[request1,request2]];
}
// 接收到數(shù)據(jù)后在這里統(tǒng)一reloadData
- (void)reloadData1:(id)Data1 Data2:(id)Data2{
NSLog(@"ReloadData%@---%@",Data1,Data2);
}
6-7 定時器
- 延時執(zhí)行
// 延時執(zhí)行
[[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{
NSLog(@"2秒后執(zhí)行我");
}];
- 定時執(zhí)行
// 定時執(zhí)行 takeUntil 要條件限制一下 否則當控制器銷毀后 還是會繼續(xù)執(zhí)行
[[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]]takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {
NSLog(@"每隔1s會執(zhí)行");
}];
7 ReactiveCocoa 開發(fā)中常見的宏
7-1 RAC(TARGET, ...) 用于給某個對象的某個屬性綁定
RAC(self.label,text) = self.textFiled.rac_textSignal;
7-2 RACObserve(TARGET, KEYPATH) 監(jiān)聽某個對象的某個屬性 返回的是信號
[RACObserve(self.textFiled,center ) subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
7-3 RACTuplePack 把數(shù)據(jù)包裝成RACTuple (元祖類) RACTupleUnpack 把元祖解包成對應的數(shù)據(jù)
// 把參數(shù)中的數(shù)據(jù)包裝成元祖
RACTuple *tuple = RACTuplePack(@10,@20,@30);
// 要一一對應付
RACTupleUnpack(NSString *name,NSString *name2,NSString *name3) = tuple;
NSLog(@"%@---%@---%@",name,name2,name3);
本文章借鑒網(wǎng)絡多篇文章 僅為學習筆記記錄