1.ReactiveCocoa是什么阱当?
ReactiveCocoa(簡稱為RAC),是由Github開源的一個應(yīng)用于iOS和OS開發(fā)的新框架,Cocoa是蘋果整套框架的簡稱药版,因此很多蘋果框架喜歡以Cocoa結(jié)尾。
關(guān)鍵詞:ReactiveCocoa是Github開源的一個框架
2.ReactiveCocoa有什么用炼邀?
在iOS開發(fā)過程中陆错,經(jīng)常會響應(yīng)某些事件來處理某些業(yè)務(wù)邏輯灯抛,例如按鈕的點擊,上下拉刷新音瓷,網(wǎng)絡(luò)請求对嚼,屬性的變化(通過KVO)或者用戶位置的變化(通過CoreLocation)。但是這些事件都用不同的方式來處理绳慎,比如action纵竖、delegate、KVO杏愤、callback等靡砌。
其實這些事件,都可以通過RAC處理声邦,ReactiveCocoa為事件提供了很多處理方法乏奥,而且利用RAC處理事件很方便,可以把要處理的事情亥曹,和監(jiān)聽的事情的代碼放在一起邓了,這樣非常方便我們管理,就不需要跳到對應(yīng)的方法里媳瞪。非常符合我們開發(fā)中高聚合骗炉,低耦合
的思想。
關(guān)鍵詞:在iOS日常開發(fā)過程中使用的一些處理事件的方法蛇受,RAC也能處理并且更方便
3.已知的編程思想都有哪些句葵?
- 面向過程
- 處理事情以過程為核心,一步一步的實現(xiàn)。
- 面向?qū)ο?
- 萬物皆對象
- 鏈?zhǔn)骄幊趟枷?
- 是將多個操作(多行代碼)通過點號(.)鏈接在一起成為一句代碼,使代碼可讀性好乍丈。
- 響應(yīng)式編程思想
- 不需要考慮調(diào)用順序剂碴,只需要知道考慮結(jié)果,類似于蝴蝶效應(yīng)轻专,產(chǎn)生一個事件忆矛,會影響很多東西,這些事件像流一樣的傳播出去请垛,然后影響結(jié)果催训,借用面向?qū)ο蟮囊痪湓挘f物皆是流宗收。
- 函數(shù)式編程思想
- 是把操作盡量寫成一系列嵌套的函數(shù)或者方法調(diào)用漫拭。
- 函數(shù)響應(yīng)式編程(FRP)
- 不需要考慮調(diào)用順序,直接考慮結(jié)果混稽,把每一次操作都寫成一系列嵌套的方法中采驻,使代碼高聚合,方便管理荚坞。
4.如何導(dǎo)入ReactiveCocoa框架挑宠?
- 這里使用CocoaPods來導(dǎo)入
- 創(chuàng)建一個新的工程演示下框架的導(dǎo)入
- 打開終端,進(jìn)入工程文件的同級目錄
- 新建一個profile文件颓影,輸入一下內(nèi)容并保存
use_frameworks!
pod 'ReactiveCocoa', '~> 4.0.2-alpha-1'
- 在終端輸入指令
pod install
完成安裝
5.ReactiveCocoa常見類有哪些?
第1種: RACSignal 信號類
操作步驟:
- 創(chuàng)建信號(冷信號)
- 訂閱信號(熱信號)
- 發(fā)送數(shù)據(jù)
// 1.創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// block什么時候調(diào)用:當(dāng)信號被訂閱的時候就會調(diào)用
// block作用:在這里面?zhèn)鬟f數(shù)據(jù)出去
// 3.發(fā)送數(shù)據(jù)
[subscriber sendNext:@1];
return nil;
}];
// 2.訂閱信號
// x:信號傳遞出來的數(shù)據(jù)
[signal subscribeNext:^(id x) {
// block什么時候調(diào)用:當(dāng)信號內(nèi)部,發(fā)送數(shù)據(jù)的時候,就會調(diào)用,并且會把值傳遞給你
// block作用:在這個block中處理數(shù)據(jù)
NSLog(@"%@",x);
}];
RACSignal:表示有數(shù)據(jù)傳遞的時候
RACDisposable:取消訂閱信號
RACSubscriber:訂閱者,發(fā)送數(shù)據(jù)
/*
執(zhí)行流程:
1.創(chuàng)建信號RACDynamicSignal
* 1.1 把didSubscribe保存到RACDynamicSignal
2.訂閱信號
* 2.1 創(chuàng)建訂閱者,把nextBlock保存到訂閱者里面去
* 2.2 就會調(diào)用信號的didSubscribe
3.執(zhí)行didSubscribe
* 3.1 拿到訂閱者發(fā)送訂閱者
* [subscriber sendNext:@1]內(nèi)部就是拿到訂閱者的nextBlock
* 信號被訂閱,就會執(zhí)行創(chuàng)建信號時didSubscribe
* 訂閱者發(fā)送信號,就是調(diào)用nextBlock
*/
第2種: RACDisposable 取消訂閱或者清理資源
操作步驟:
- 創(chuàng)建信號
- 訂閱信號
- 發(fā)送信號
// 只要訂閱者一直在,表示需要一直訂閱信號,信號不會自動被取消訂閱
// 1.創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
_subscriber = subscriber;
// 3.發(fā)送信號
[subscriber sendNext:@1];
return [RACDisposable disposableWithBlock:^{
// 當(dāng)信號取消訂閱的時候就會調(diào)用
NSLog(@"信號被取消訂閱");
}];
}];
// 2.訂閱信號
RACDisposable *disposable = [signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 取消訂閱(主動取消)
[disposable dispose];
}
第3種:RACSubject 信號提供者
信號提供者:既可以充當(dāng)信號,也可以充當(dāng)訂閱者,發(fā)送數(shù)據(jù) 一個信號允許被多次訂閱
操作步驟:
- 創(chuàng)建信號
- 訂閱信號
- 發(fā)送信號
// 1.創(chuàng)建信號
RACSubject *subject = [RACSubject subject];
// 2.訂閱信號
[subject subscribeNext:^(id x) {
NSLog(@"訂閱者一%@",x);
}];
[subject subscribeNext:^(id x) {
NSLog(@"訂閱者二%@",x);
}];
// 3.發(fā)送信號
[subject sendNext:@1];
/*
執(zhí)行流程:
1.創(chuàng)建信號
2.訂閱信號
* 創(chuàng)建訂閱者
* [self subscribe:o]訂閱信號,僅僅是把訂閱者保存起來.
3.發(fā)送信號
* 把所有的訂閱者遍歷出來,一個一個的調(diào)用它們nextBlock
*/
第4種: RACReplaySubject 重復(fù)提供信號類(RACSubject的子類)
允許先發(fā)送信號,在訂閱信號 重復(fù)信號提供者
操作步驟:
- 創(chuàng)建信號
- 訂閱信號
- 發(fā)送信號
// 1.創(chuàng)建信號
RACReplaySubject *subject = [RACReplaySubject subject];
// 2.發(fā)送信號
[subject sendNext:@"123123"];
[subject sendNext:@"345"];
[subject sendNext:@"456456"];
// 1.把值保存到數(shù)組
// 2.遍歷所有的訂閱者,調(diào)用nextBlock
// 3.訂閱信號
[subject subscribeNext:^(id x) {
NSLog(@"訂閱者一%@",x);
}];
// 1.遍歷所有值,拿到訂閱者去發(fā)送
[subject subscribeNext:^(id x) {
NSLog(@"訂閱者二%@",x);
}];
/*
執(zhí)行流程:
1.創(chuàng)建信號
2.訂閱信號
* 創(chuàng)建訂閱者,保存nextBlock保存
* 遍歷valuesReceived需要發(fā)送的所有值,拿到一個一個值,利用訂閱者發(fā)送數(shù)據(jù)
3.發(fā)送信號
* 把發(fā)送的值,保存到數(shù)組
* 把所有的訂閱者遍歷出來,一個一個的調(diào)用它們nextBlock
*/
第5種:RACMulticastConnection
用于當(dāng)一個信號懒鉴,被多次訂閱時诡挂,為了保證創(chuàng)建信號時,避免多次調(diào)用創(chuàng)建信號中的block临谱,造成副作用璃俗,可以使用這個類處理
簡單使用
// 1.創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"發(fā)送請求");
// 3.發(fā)送信號
[subscriber sendNext:@"網(wǎng)絡(luò)數(shù)據(jù)"];
return nil;
}];
// 2.把信號轉(zhuǎn)換成連接類
RACMulticastConnection *connect = [signal publish];
// 3.訂閱連接類的信號,注意:一定是訂閱連接類的信號,不再是源信號
[connect.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[connect.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[connect.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 4.連接
[connect connect];
一個信號即使被訂閱多次,也只是發(fā)送一次請求 RACMulticastConnection:用于信號中請求數(shù)據(jù),避免多次請求數(shù)據(jù)
/*
執(zhí)行流程
1.創(chuàng)建信號
* 創(chuàng)建RACDynamicSignal,并且把didSubscribe保存到
2.把信號轉(zhuǎn)換成連接類
* 創(chuàng)建信號提供者RACSubject
* [self multicast:subject]:設(shè)置原始信號的多點傳播subject,本質(zhì)就是把subject設(shè)置為原始信號的訂閱者
* 創(chuàng)建RACMulticastConnection,把原始信號保存到_sourceSignal,把subject保存到_signal
3.保存訂閱者
4.連接 [connect connect]
* 訂閱_sourceSignal,并且設(shè)置訂閱者為subject
5.執(zhí)行didSubscribe
6.[subject sendNext]遍歷所有的訂閱者發(fā)送信號
*/
第6種:RACCommand 用于處理事件的類
RAC中用于處理事件的類,可以把事件如何處理,事件中的數(shù)據(jù)如何傳遞悉默,包裝到這個類中城豁,它可以很方便的監(jiān)控事件的執(zhí)行過程
- 使用場景: 監(jiān)聽按鈕點擊,網(wǎng)絡(luò)請求
- RACCommand使用步驟:創(chuàng)建命令 -> 執(zhí)行命令
- RACCommand使用注意點:內(nèi)部不允許傳入一個nil的信號
// 1.創(chuàng)建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// signalBlock調(diào)用時刻:只要命令一執(zhí)行就會調(diào)用
// signalBlock作用:處理事件
NSLog(@"%@",input);
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"didSubscribe");
// didSubscribe調(diào)用時刻:執(zhí)行命令過程中,就會調(diào)用
// didSubscribe作用:傳遞數(shù)據(jù)
// subscriber -> [RACReplaySubject subject]
// RACReplaySubject:把值保存起來,遍歷所有的訂閱者發(fā)送這個值
[subscriber sendNext:@1];
return nil;
}];
}];
// 2.執(zhí)行命令
RACReplaySubject *replaySubject = (RACReplaySubject *)[command execute:@"執(zhí)行命令"];
// 3.獲取命令中產(chǎn)生的數(shù)據(jù),訂閱信號
[replaySubject subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 1.創(chuàng)建訂閱者,訂閱信號
// 2.遍歷所有值,拿到訂閱者去發(fā)送
/*
執(zhí)行流程:
// 1.創(chuàng)建命令
* 把signalBlock保存到命令中
// 2.執(zhí)行命令
* 調(diào)用命令signalBlock
* 創(chuàng)建多點傳播連接類, 訂閱源信號,并且設(shè)置源信號的訂閱者為RACReplaySubject
* 返回源信號的訂閱者
*/
switchToLatest用法
// 1.創(chuàng)建了一個信號中的信號,只能發(fā)送信號
RACSubject *signalOfSignals = [RACSubject subject];
// 創(chuàng)建信號,發(fā)送普通數(shù)據(jù)
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
// 2.通過訂閱信號中信號,拿到signal發(fā)出值
// 獲取信號中的信號發(fā)送最新信號
[signalOfSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 3.發(fā)送信號
// 信號中的信號發(fā)送數(shù)據(jù)
[signalOfSignals sendNext:signalA];
[signalOfSignals sendNext:signalB];
// 信號發(fā)送數(shù)據(jù)
[signalB sendNext:@"發(fā)送普通數(shù)據(jù)"];
// 1.創(chuàng)建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// 1.命令執(zhí)行的時候調(diào)用
NSLog(@"執(zhí)行SignalBlock");
// 處理事情,網(wǎng)絡(luò)請求
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 2.執(zhí)行完SignalBlock,接著就會調(diào)用
NSLog(@"執(zhí)行didSubscribe");
// 傳送數(shù)據(jù),也只會來一次
[subscriber sendNext:@"請求到網(wǎng)絡(luò)數(shù)據(jù)"];
// 一定要做事情,聲明數(shù)據(jù)傳遞完成
// 當(dāng)數(shù)據(jù)傳遞完成,命令就執(zhí)行完成
[subscriber sendCompleted];
return nil;
}];
}];
// 直接獲取命令中新發(fā)出信號
// switchToLatest:只能用于signalOfSignals
// 作用:就是拿到signalOfSignals發(fā)出的最新信號
[command.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 訂閱當(dāng)前命令執(zhí)行狀態(tài)的信號,正在執(zhí)行,沒有執(zhí)行
[command.executing subscribeNext:^(id x) {
// x:YES 正在執(zhí)行
// x:No 沒有執(zhí)行/執(zhí)行完成
if ([x boolValue] == YES) {
NSLog(@"正在執(zhí)行");
}else{
NSLog(@"沒有執(zhí)行/執(zhí)行完成");
}
}];
// 2.執(zhí)行命令
RACSignal *signal = [command execute:@1];
6.ReactiveCocoa常用集合類抄课?
RACTuple 和RACSequence 的使用
RACTuple: 元組類,類似NSArray,用來包裝值. RACSequence: RAC中的集合類唱星,用于代替NSArray,NSDictionary,可以使用它來快速遍歷數(shù)組和字典
簡單使用
RACTuple *tuple = [RACTuple tupleWithObjectsFromArray:@[@"1",@1,@3,@5]];
NSString *str = tuple[0];
OC->RAC
NSArray *arr = @[@"123",@1,@3,@5];
// OC數(shù)組轉(zhuǎn)換成RAC集合
RACSequence *sequence = arr.rac_sequence;
// 把集合轉(zhuǎn)換成signal
RACSignal *signal = sequence.signal;
// 訂閱集合類的信號,只要訂閱這個信號,就會遍歷集合中所有元素
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[arr.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
宏的使用
NSDictionary *dict = @{@"name":@"xmg",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
// id value = x[1];
// id key = x[0];
// 宏的參數(shù),存放需要生成的變量名
// 宏會自動生成參數(shù)里面的變量
RACTupleUnpack(id key,id value) = x;
NSLog(@"%@ : %@",key,value);
}];
字典轉(zhuǎn)模型
方式一:
// RAC:集合,相當(dāng)于數(shù)組或者字典
// 這個類的創(chuàng)建必須要依賴于數(shù)組或者字典
// 解析plist
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
_flags = [NSMutableArray array];
[dictArr.rac_sequence.signal subscribeNext:^(NSDictionary *x) {
Flag *flag = [Flag flagWithDict:x];
[_flags addObject:flag];
}];
方式二:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
_flags = [NSMutableArray array];
_flags = [[dictArr.rac_sequence map:^id(id value) {
// value:就是原始信號發(fā)送的值,字典
// block返回值就是需要映射的對象
return [Flag flagWithDict:value];
}] array];
NSLog(@"%@",_flags);