ReactCocoa使用

通過Cocoapods集成pod ‘ReactiveObjC’

然後在項目中導入 #import <ReactiveObjC/ReactiveObjC.h>

創建RACSignal 對象,並且發送消息

@weakify(self)
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {

        @strongify(self)

        self.data = [[Model alloc] init];

        self.data.nameStr = @"測試完成";

        [subscriber sendNext:self.data];

        [subscriber sendCompleted];
         return nil;
    }];
     [signal subscribeNext:^(id  _Nullable x)
    {
        
        
        NSLog(@"x==========%@\n",x);
    }];
    下面是另外一種寫法
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        [subscriber sendNext:@"1"];
        
        return [RACDisposable disposableWithBlock:^{
            
        }];;
    }];
    
    
    [signal subscribeNext:^(id  _Nullable x) {
       NSLog(@"結果是========%@",x);
    }];

將上面的RAC轉換成flatten

  RACSignal *flattenMapSignal = [signal flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {

        return RACObserve(self.data, nameStr);
    }];

    [flattenMapSignal subscribeNext:^(id  _Nullable x) {


        NSLog(@"結果是=========%@\n",x);
    }];

創建RACSubject對象,執行完之後,就會執行rac_willDeallocSignal 方法

RACSubject *subject = [RACSubject subject]; 
 [subject.rac_willDeallocSignal subscribeCompleted:^{

    }];
     [subject subscribeNext:^(id x) { //3
        NSLog(@"next = %@", x);
    }];
     [subject sendNext:@1];

UITextField綁定textSignal 輸出結果

   
    [[_textField.rac_textSignal bind:^RACSignalBindBlock _Nullable{
        return ^RACSignal *(id value,BOOL *stop){
            return [RACReturnSignal return:[NSString stringWithFormat:@"輸出:%@",value]];
        };
    }]subscribeNext:^(id  _Nullable x) {
        NSLog(@"結果是=====%@\n",x);
    }] ;

RACReplaySubject 傳的信號會重複播放

// 1.創建信號
 //1.創建信號
    RACReplaySubject *replaySubject = [RACReplaySubject subject];
    //2.發送信號
    [replaySubject sendNext:@1];
    [replaySubject sendNext:@2];
    //3.訂閱信號
    [replaySubject subscribeNext:^(id x) {
        NSLog(@"第一個訂閱者接收到的數據%@",x);
    }];
    //訂閱信號
    [replaySubject subscribeNext:^(id x) {
        NSLog(@"第二個訂閱者接收到的數據%@",x);
    }];

retry 當信號出錯的時候 重新執行信號操作

    __block int i = 0;
    [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        if(i==10)
        {
            [subscriber sendNext:@1];
        }else{
            NSLog(@"接收到錯誤");
            [subscriber sendError:nil];
        }
        i++;
        return nil;
     }] retry] subscribeNext:^(id x) {
        NSLog(@"retry%@",x);
     } error:^(NSError *error) {
     }];

delay 延遲2s執行

   RACSignal *signal = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        [subscriber sendNext:@1];
        
        return nil;
    
    }] delay:2] subscribeNext:^(id x) {
         NSLog(@"%@",x);
    
    }];

RACScheduler 定時做任務,當離開當前頁面取消任務

   self.disposable = [[[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSDate * _Nullable x) {
         NSLog(@"做完這件事");
         [self.disposable dispose];
      }];

timeout 可以讓信號在一定的時間後,自動報錯

    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *         _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        return  nil;
     }]timeout:1 onScheduler:[RACScheduler currentScheduler]];
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"====%@\n",x);
    } error:^(NSError * _Nullable error) {
        //1秒後會自動調用
        NSLog(@"%@",error);
    }];

觀察某個對象的某個值的變化,並進行過濾

[[RACObserve(self,self.data) filter:^BOOL(id  _Nullable value) {
        return value;
    }] subscribeNext:^(Model *x) {
        NSLog(@"執行了這裏=======%@\n",x.nameStr);
    }];

NSNotificationCenter 之觀察

 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"postData" object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"結果是-------%@\n",x.userInfo);
    }];
    監聽按鈕的事件
     UIButton *button  =[[UIButton alloc]initWithFrame:CGRectMake(50, 100, 30, 30)];
    button.backgroundColor =[UIColor redColor];
    [self.view addSubview:button];
    [[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
    }];

flattenMap 將信號包裝一層發送出去

[[self.phoneTextView.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
        return [RACReturnSignal return:[NSString stringWithFormat:@"輸出:%@",value]];
    }]subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

concat:按一定順序拼接信號,當多個信號發出的時候,有順序的接收信號,把signalA拼接到signalB後,signalA發送完成,signalB纔會被激活。訂閱拼接的信號,不需要單獨訂閱signalA,signalB
注意:第一個信號必鬚髮送完成,第二個信號纔會被激活

 RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        [subscriber sendNext:@1];
        
        [subscriber sendCompleted];
        
        return nil;
    }];
    RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       [subscriber sendNext:@2];
        return nil;
    }];
    RACSignal *concatSignal = [signalA concat:signalB];
    [concatSignal subscribeNext:^(id x) {
        NSLog(@"kl==========%@",x);
    }];

then:用於連接兩個信號,當第一個信號完成,纔會連接then返回的信號
then:用於連接兩個信號,當第一個信號完成,纔會連接then返回的信號
注意使用then,之前信號的值會被忽略掉.
底層實現:1、先過濾掉之前的信號發出的值。2.使用concat連接then返回的信號

   [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendCompleted];
        return nil;
    }] then:^RACSignal *{
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [subscriber sendNext:@12];
            return nil;
        }];
    }] subscribeNext:^(id x) {
        // 只能接收到第二個信號的值,也就是then返回信號的值
        NSLog(@"then================%@",x);
    }];

merge:把多個信號合併爲一個信號,任何一個信號有新值的時候就會調用,merge:把多個信號合併成一個信號,創建多個信號
底層實現:
// 1.合併信號被訂閱的時候,就會遍歷所有信號,並且發出這些信號。
// 2.每發出一個信號,這個信號就會被訂閱
// 3.也就是合併信號一被訂閱,就會訂閱裏面所有的信號。
// 4.只要有一個信號被髮出就會被監聽。

 //`merge`:把多個信號合併爲一個信號,任何一個信號有新值的時候就會調用
       //merge:把多個信號合併成一個信號
       //創建多個信號
       RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

           [subscriber sendNext:@1];
           return nil;
       }];
       RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [subscriber sendNext:@2];
            return nil;
       }];
       //合併信號,任何一個信號發送數據,都能監聽到.
       RACSignal *mergeSignal = [signalA merge:signalB];
       [mergeSignal subscribeNext:^(id x) {
           NSLog(@"merge==========%@\n",x);
       }];

zipWith 把兩個信號壓縮成一個信號,只有當兩個信號同時發出信號內容時,並且把兩個信號的內容合併成一個元祖,纔會觸發壓縮流的next事件
底層實現:
// 1.定義壓縮信號,內部就會自動訂閱signalA,signalB
// 2.每當signalA或者signalB發出信號,就會判斷signalA,signalB有沒有發出個信號,有就會把最近發出的信號都包裝成元組發出。

 RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@1];
        return nil;
    }];
     RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@2];
        return nil;
    }];
    //壓縮信號A,信號B
    RACSignal *zipSignal = [signalA zipWith:signalB];
    [zipSignal subscribeNext:^(RACTwoTuple *x)
    {
        NSLog(@"zipWith============%@,%@\n\n",x.first,x.second);
    }];

combineLatest 將多個信號合併起來,並且拿到各個信號的最新的值,
// 底層實現:
// 1.當組合信號被訂閱,內部會自動訂閱signalA,signalB,必須兩個信號都發出內容,纔會被觸發。
// 2.並且把兩個信號組合成元組發出。

 RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        [subscriber sendNext:@1];
        return nil;
    }];
    
    RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        [subscriber sendNext:@5];
        return nil;
    }];
    
    // 把兩個信號組合成一個信號,跟zip一樣,沒什麼區別
    RACSignal *combineSignal = [signalA combineLatestWith:signalB];
    
    [combineSignal subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];

reduce聚合:用於信號發出的內容是元組,把信號發出元組的值聚合成一個值,聚合
常見的用法,(先組合在聚合)。combineLatest:(id)signals reduce:(id (^)())reduceBlock
// reduce中的block簡介:
// reduceblcok中的參數,有多少信號組合,reduceblcok就有多少參數,每個參數就是之前信號發出的內容
// reduceblcok的返回值:聚合信號之後的內容。
底層實現:訂閱聚合信號,每次有內容發出,就會執行reduceblcok,把信號內容轉換成reduceblcok返回的值

 RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
         [subscriber sendNext:@1];
         return nil;
     }];
       RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber)
     {
         [subscriber sendNext:@8];
         return nil;
     }];
      RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber *num1 ,NSNumber *num2){

        return [NSString stringWithFormat:@"%@ %@",num1,num2];

    }];
    
     [reduceSignal subscribeNext:^(id x) {

         NSLog(@"%@",x);
     }];

filter:過濾信號,使用它可以獲取滿足條件的信號. 每次信號發出,會先執行過濾條件判斷

    [_textField.rac_textSignal filter:^BOOL(NSString *value) {
            return value.length > 3;
    }];

ignore:忽略完某些值的信號.

  [[_phoneTextView.rac_textSignal ignore:@"1"] subscribeNext:^(id x) {

        NSLog(@"%@",x);
    }];

distinctUntilChanged:當上一次的值和當前的值有明顯的變化就會發出信號,否則會被忽略掉。
// 過濾,當上一次和當前的值不一樣,就會發出內容。
// 在開發中,刷新UI經常使用,只有兩次數據不一樣才需要刷新

 [[_phoneTextView.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {

       NSLog(@"%@",x);
   }];

take:從開始一共取N次的信號 1、創建信號

//    RACSubject *signal = [RACSubject subject];
//
//    // 2、處理信號,訂閱信號
//    [[signal take:3] subscribeNext:^(id x) {
//
//        NSLog(@"%@",x);
//    }];
//
//    // 3.發送信號
//    [signal sendNext:@1];
//
//    [signal sendNext:@6];
//     [signal sendNext:@61];
    
    
//    takeLast:取最後N次的信號,前提條件,訂閱者必須調用完成,因爲只有完成,就知道總共有多少信號.
 // 1、創建信號
//    RACSubject *signal = [RACSubject subject];
//
//    // 2、處理信號,訂閱信號
//    [[signal takeLast:1] subscribeNext:^(id x) {
//
//        NSLog(@"%@",x);
//    }];
//
//    // 3.發送信號
//    [signal sendNext:@1];
//
//    [signal sendNext:@2];
//[signal sendNext:@232];
//    [signal sendCompleted];
    
//    takeUntil:(RACSignal *):獲取信號直到某個信號執行完成

takeUntil 噹噹前對象被銷燬時,停止執行

 [_textField.rac_textSignal takeUntil:self.rac_willDeallocSignal];

skip:(NSUInteger):跳過幾個信號,不接受

 [_phoneTextView.rac_textSignal skip:1] subscribeNext:^(id x) {
        NSLog(@"%@",x);
  }];

switchToLatest 用於signalOfSignals(信號的信號),有時候信號也會發出信號,會在signalOfSignals中,獲取signalOfSignals發送的最新信號。

RACSubject *signalOfSignals = [RACSubject subject];
   RACSubject *signal = [RACSubject subject];

    // 獲取信號中信號最近發出信號,訂閱最近發出的信號。
    // 注意switchToLatest:只能用於信號中的信號
    [signalOfSignals.switchToLatest subscribeNext:^(id x) {


        NSLog(@"%@",x);
    }];
    [signalOfSignals sendNext:signal];
    [signal sendNext:@1];

ReactiveCocoa操作方法之秩序。
doNext: 執行Next之前,會先執行這個Block
doCompleted: 執行sendCompleted之前,會先執行這個Block

    [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendCompleted];
        return nil;
    }] doNext:^(id x) {
        // 執行[subscriber sendNext:@1];之前會調用這個Block
        NSLog(@"doNext");;
    }] doCompleted:^{
        // 執行[subscriber sendCompleted];之前會調用這個Block
        NSLog(@"doCompleted");;
        
    }] subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];

ReactiveCocoa操作方法之線程

deliverOn: 內容傳遞切換到制定線程中,副作用在原來線程中,把在創建信號時block中的代碼稱之爲副作用
 subscribeOn: 內容傳遞和副作用都會切換到制定線程中。

數組操作

Array *numbers = @[@1,@2,@3,@4];

    [numbers.rac_sequence.signal subscribeNext:^(id  _Nullable x) {

        NSLog(@"數據=======%@\n",x);
    }];

字典操作

 
    NSDictionary *dict = @{@"name":@"xmg",@"age":@10};

    [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {

        RACTupleUnpack(NSString *key,NSString *value) = x;

        NSLog(@"===%@",key);

        NSLog(@"=====%@",value);


    }];

map 映射成新的數據

NSArray *numbers = @[@1,@2,@3,@4];
NSArray *numbers2 =  [[numbers.rac_sequence map:^id _Nullable(id  _Nullable value) {

        return value;
    }]array] ;

RACCommand 命令執行

mand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {

        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {

            [subscriber sendNext:@"請求數據"];

            [subscriber sendCompleted];

            return nil;
        }];
    }];


    self.command = command;
    
    
    

//    self.btnClick.rac_command = command;

//    [self.btnClick.rac_command.executionSignals subscribeNext:^(RACSignal<id> * _Nullable x) {
//
//        NSLog(@"===%@\n",x);
//
//        [x subscribeNext:^(id  _Nullable x) {
//
//            NSLog(@"2222===%@\n",x);
//
//        }];
//    }];

   [self.command.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {

       NSLog(@"4444===%@\n",x);
   }];
   [[command.executing skip:1] subscribeNext:^(id x) {
//
//      if ([x boolValue] == YES) {
//          // 正在執行
//          NSLog(@"正在執行");
//
//      }else{
//          // 執行完成
//          NSLog(@"執行完成");
//      }
//
//  }];
 [self.command execute:@1];

1.代替代理
// 需求:自定義redView,監聽紅色view中按鈕點擊
// 之前都是需要通過代理監聽,給紅色View添加一個代理屬性,點擊按鈕的時候,通知代理做事情
// rac_signalForSelector:把調用某個對象的方法的信息轉換成信號,就要調用這個方法,就會發送信號。
// 這裏表示只要redV調用btnClick:,就會發出信號,訂閱就好了。

 [[redV rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
//         NSLog(@"點擊紅色按鈕");
//     }];
// 2.KVO
//     // 把監聽redV的center屬性改變轉換成信號,只要值改變就會發送信號
//     // observer:可以傳入nil
//     [[redV rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
//
//         NSLog(@"%@",x);
//
//     }];

//    // 把按鈕點擊事件轉換爲信號,點擊按鈕,就會發送信號
//    [[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
//
//        NSLog(@"按鈕被點擊了");
//    }];
//
//    // 4.代替通知
//    // 把監聽到的通知轉換信號
//    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
//        NSLog(@"鍵盤彈出");
//    }];
    
    
//    // 6.處理多個請求,都返回結果的時候,統一做處理.
//        RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//
//            // 發送請求1
//            [subscriber sendNext:@"發送請求1"];
//            return nil;
//        }];
//
//        RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//            // 發送請求2
//            [subscriber sendNext:@"發送請求2"];
//            return nil;
//        }];
//
//        // 使用注意:幾個信號,參數一的方法就幾個參數,每個參數對應信號發出的數據。
//        [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];

屬性綁定

 RAC(self.labelView,text) = _textField.rac_textSignal;
 [RACObserve(self.view, center) subscribeNext:^(id x) {

        NSLog(@"%@",x);
    }];

將數據包裝成元祖

RACTuple *tuple = RACTuplePack(@10,@20);
TupleUnpack(NSString *number) = tuple;

    [[[tuple.rac_sequence map:^id _Nullable(id  _Nullable value) {

        return value;
    }]signal]subscribeNext:^(id  _Nullable x) {
        NSLog(@"number============%@\n",x);
    }];

throttle 節流,當某個信號發送比較頻繁的時候,可以使用節流

//    節流:當某個信號發送比較頻繁時,可以使用節流,在某一段時間不發送信號內容,過了一段時間獲取信號的最新內容發出。
//    RACSubject *subject = [RACSubject subject];
//    // 節流1秒,1秒後接收最後一個發送的信號
//    [[subject throttle:1] subscribeNext:^(id x) {
//        NSLog(@"%@", x);
//    }];
//    [subject sendNext:@1];
//    [subject sendNext:@2];
//    [subject sendNext:@3];
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章