ReactiveCocoa學(xué)習(xí)

前言

前段時間學(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容