前言
前段時間學(xué)習(xí)ReactiveCocoa基礎(chǔ),總結(jié)出來一些常用的方法,希望對學(xué)習(xí)ReactiveCocoa人有所幫助.
ReactiveCocoa簡介
- ReactiveCocoa(簡稱為RAC),是由Github開源的一個應(yīng)用于iOS和OS開發(fā)的新框架.github地址.
1.ReactiveCocoa的思想
- 函數(shù)式編程思想:是把操作盡量寫成一系列嵌套的函數(shù)或者方法調(diào)用。
- 函數(shù)式編程特點:每個方法必須有返回值(本身對象),把函數(shù)或者Block當(dāng)做參數(shù),block參數(shù)(需要操作的值)block返回值(操作結(jié)果)
2.ReactiveCocoa常見的類
- RACSiganl:信號類,在RAC中最核心的類,他本身不具備發(fā)送信號的能力
- RACSiganl簡單的應(yīng)用:
#pragma mark - RACSignal
- (void)RACSignal {
// RACSignal 有數(shù)據(jù)產(chǎn)生的時候 就會使用RACSignal RACSignal是不能發(fā)送信號的
//RACSignal使用步驟: 1.創(chuàng)建信號(冷信號) 2.訂閱信號(熱信號) 3.發(fā)送信號
//RACSignal使用步驟
//1.創(chuàng)建信號(冷信號)
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//didsubscriber調(diào)用:只要一個信號被訂閱就會調(diào)用
//didsubscriber作用:發(fā)送數(shù)據(jù)
//3.發(fā)送信號
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}];
//2.訂閱信號(熱信號)
[signal subscribeNext:^(id x) {
//nextBlock調(diào)用:只要訂閱者發(fā)送數(shù)據(jù)就會調(diào)用
//nextBlock作用:處理數(shù)據(jù) 展示到UI界面
// x 信號發(fā)送的內(nèi)容
NSLog(@"%@",x);
}];
}
- RACDisposable:用于取消訂閱或者清理資源,信號發(fā)送完成或者發(fā)送失敗的時候會觸發(fā)他.
- RACDisposable簡單的應(yīng)用:
#pragma mark - RACDisposable
- (void)RACDisposable {
//1.創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//3.發(fā)送信號
[subscriber sendNext:@"123"];
// [subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
//只要我的信號 取消訂閱就會來這
//清空資源
NSLog(@"信號取消訂閱");
}];
}];
//2.訂閱信號
RACDisposable *disposable = [signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//默認(rèn)一個信號發(fā)送數(shù)據(jù)完畢就會主動取消訂閱
//只要訂閱者在 就不會自動取消信號訂閱
//取消訂閱
[disposable dispose];
}
- RACSubject:信號提供者,自己可以充當(dāng)信號,又能發(fā)送信號,通常代替代理.
- RACSubject:簡單的應(yīng)用:
- 在使用RACSubject時候,如果進行map操作,一定要發(fā)送完成信號,不然會內(nèi)存泄露
#pragma mark - RACSubject
- (void)RACSubject {
//1.創(chuàng)建信號
RACSubject *subject = [RACSubject subject];
//2.訂閱信號
//不同信號訂閱的方式不一樣
//RACSubject處理訂閱:僅僅是保存訂閱者
[subject subscribeNext:^(id x) {
NSLog(@"接收到信號");
}];
//3.發(fā)送數(shù)據(jù)
[subject sendNext:@1];
//底層實現(xiàn):遍歷所有的訂閱者,調(diào)用nextBlock
//RACSubject被訂閱,僅僅是保存訂閱者
//執(zhí)行流程
}
- RACSubject替換代理
// 需求:
// 1.給當(dāng)前控制器添加一個按鈕,modal到另一個控制器界面
// 2.另一個控制器view中有個按鈕,點擊按鈕,通知當(dāng)前控制器
步驟一:在第二個控制器.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
RACCommand是RAC很重要的組成部分,通常用來表示某個action的執(zhí)行。
使用場景: 監(jiān)聽按鈕點擊 網(wǎng)絡(luò)請求
RACCommand的簡單的應(yīng)用:
#pragma mark - RACCommand
- (void)RACCommand {
//RACCommand: 處理事件
//1.創(chuàng)建命令
RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal *(id input) {
//input: 執(zhí)行命令傳入的參數(shù)
//Block: 執(zhí)行命令的時候就會調(diào)用
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//發(fā)送數(shù)據(jù)
[subscriber sendNext:@"發(fā)送數(shù)據(jù)"];
[subscriber sendCompleted];
return nil;
}];
}];
//如何拿到執(zhí)行命令中產(chǎn)生的數(shù)據(jù)
//訂閱命令內(nèi)部的信號
// //執(zhí)行命令
// RACSignal *signal = [command execute:@1];
// //1.方式一 直接訂閱執(zhí)行命令返回的信號
// [signal subscribeNext:^(id x) {
// NSLog(@"%@",x);
// }];
//1.方式二 executionSignals: 信號源 信號中的信號 executionSignals:信號:發(fā)送數(shù)據(jù)就是信號
//注意:必須要執(zhí)行命令訂閱
// [command.executionSignals subscribeNext:^(RACSignal *x) {
//
// [x subscribeNext:^(id x) {
// NSLog(@"%@",x);
// }];
// }];
//switchToLatest獲取最新發(fā)送的信號,只能用于信號中信號
[command.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[command execute:@1];
}
3.ReactiveCocoa開發(fā)中簡單應(yīng)用
- 代替代理 rac_signalForSelector不需要傳值 (和RACSubject類似,RACSubject需要傳值)
[[_redview rac_signalForSelector:@selector(btnredclick:)] subscribeNext:^(id x) {
NSLog(@"控制器知道按鈕被點擊");
}];
- 監(jiān)聽事件
//_btn UIButton
[[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
NSLog(@"按鈕被點擊了"); }];
- 代替通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
NSLog(@"%@",x); }];
- 監(jiān)聽文本框
// _textField UITextField
[[_textField rac_textSignal] subscribeNext:^(id x) {
NSLog(@"%@",x); }];
- RACSequence遍歷數(shù)組
NSArray *array = @[@"67",@"45",@"12"];
//array.rac_sequence轉(zhuǎn)換成集合
//array.rac_sequence.signal集合轉(zhuǎn)化成信號
//subscribeNext 訂閱信號 內(nèi)部會自動遍歷所有的元素法發(fā)出來
[array.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x); }];
- RACSequence遍歷字典
NSDictionary *dict = @{@"niming":@"小明",@"ok":@"好的"};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
//RACTuplePack:用來解析元組
//宏里面的參數(shù) 傳需要解析出來的變量名
// = 右邊,放需要解析的元組
RACTupleUnpack(NSString *key,NSString *value) = x;
NSLog(@"%@ %@",key,value);
}];
- 當(dāng)一個界面有多次請求時候, 需要保證全部請求完成,才能搭建界面
//數(shù)組: 存放信號
//數(shù)組中的所有信號都發(fā)送數(shù)據(jù)時候, 才會執(zhí)行Selector
//方法的參數(shù):必須跟數(shù)組的信號--對應(yīng)
//方法的參數(shù)就是每一個信號發(fā)送的數(shù)據(jù)
[self rac_liftSelector:@selector(upDateUIwithHotData:newData:) withSignalsFromArray:@[signal,newSignal]];
RAC常用的宏
- RAC(<#TARGET, ...#>) 用來給某個對象的某個屬性綁定信號,只要產(chǎn)生信號內(nèi)容,就會給內(nèi)容給屬性賦值
基礎(chǔ)用法:
RAC(_label,text) = _textField.rac_textSignal;
等同于
//監(jiān)聽文本框的內(nèi)容
[_textField.rac_textSignal subscribeNext:^(id x) {
_label.text = x;
}];
- @weakify(Obj) @strongify(Obj) 一般兩個都是配套使用,解決循環(huán)引用問題
- RACObserve(self.view, frame) 監(jiān)聽某個對象的某個屬性,返回的是信號
- RACObserve使用時候需要注意循環(huán)引用問題 使用@weakify(Obj) @strongify(Obj)
- RACTuplePack 把數(shù)據(jù)包裝成RACTuple (元組類)
基本用法:
//包裝元組
RACTuple *tupe = RACTuplePack(@1,@2);
總結(jié)
在學(xué)習(xí)中參考了這篇文章 學(xué)習(xí)中自己寫了兩個demo登錄界面和網(wǎng)絡(luò)請求(寫了一個UITableView展示數(shù)據(jù))整理下傳到github.
登錄界面代碼github
其他學(xué)習(xí)RAC文章
ReactiveCocoa入門教程
ReactiveCocoa