ReactiveCocoa學習筆記

可拜讀《RAC核心元素與信號流》 html

1. RACSignal使用步驟及底層實現

(1) 建立信號 (RACSignal底層實現:把didSubscribe保存到信號中,還不會觸發。)ios

createSignal的意義是,建立一個signal對象,而且把參數賦值給signal的名爲didSubscribe的屬性,這個block的參數是subscriber,返回RACDisposable。fetch

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe;

(2) 訂閱信號,纔會激活信號. ui

- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;

RACSignal底層實現:spa

  (2.1) subscribeNext內部會建立訂閱者subscriber,而且把nextBlock保存到subscriber中。
  (2.2) subscribeNext內部會調用siganl的didSubscribe。
code

(使用subscribeNext訂閱信號,訂閱者(RACSubscriber) 訂閱信號,即訂閱者一旦發送了數據(三種事件:next、complete、error),就去執行回調,即subscribeNext這個block的內容orm

(3) 發送信號htm

- (void)sendNext:(id)value;

RACSignal底層實現:sendNext底層其實就是執行subscriber的nextBlock。對象

// 1. 建立信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {  
         // 當有訂閱者訂閱信號,就會調用block。
         task.success = ^(MTANetworkTask *task, id result) {
            [subscriber sendNext:result];
            // 發送信號完成,內部會自動調用[RACDisposable disposable]取消訂閱信號。
            [subscriber sendCompleted];
        };
        task.failure = ^(MTANetworkTask *task, NSError *error) {
            [subscriber sendError:[NSError errorWithTask:task error:error]];
        };
// 取消信號信號被取消時機:1.自動取消,當一個信號的訂閱者被銷燬的時候自動取消訂閱,2.手動取消
         // block調用時機:一旦一個信號被取消訂閱就會調用;block做用:當信號被取消時清空資源
         return [RACDisposable disposableWithBlock:^{  
                // block調用時機:當信號發送完成或者發送錯誤,就會自動執行這個block,取消訂閱信號。
                NSLog(@"取消訂閱");  
         }]; 
}]; 

 // 2. 訂閱信號 
RACDisposable *disposable = [signal subscribeNext:^(id x) {     
        // block調用時刻:每當有信號發出數據,就會調用block.  
         if ([x boolValue]) {
            _navView.hidden = YES;
        } else {
           _navView.hidden = NO;
          [UIView animateWithDuration:.5  animations:^{_navView.alpha = 1; }];
        } 
 }];  
// 3. 取消訂閱  
 [disposable dispose];  

 2. 經常使用RAC介紹

  按鈕的點擊使用action,ScrollView滾動使用delegate,屬性值改變使用KVO等系統提供的方式。這些事件,均可以經過RAC處理。blog

    RAC中最核心的類RACSignal,表示未來有數據傳遞,只要有數據改變,信號內部接收到數據,就會立刻發出數據.

    RAC提供signals(表現爲RACSignal)來捕捉當前以及未來的值.經過對signals進行鏈接,綁定和響應,不須要連續地觀察和更新值。

舉例:

摘抄:《ReactiveCocoa自述:工做原理和應用

(1)

// RACObserve(self, username) creates a new RACSignal that sends the current
// value of self.username, then the new value whenever it changes.
// -subscribeNext: will execute the block whenever the signal sends a value.
[RACObserve(self, username) subscribeNext:^(NSString *newName) {
    NSLog(@"%@", newName);
}];

(2) filter

signals可以鏈接在一塊兒而且可以同時進行操做:

// Only logs names that starts with "j".
//
// -filter returns a new RACSignal that only sends a new value when its block returns YES.
[[RACObserve(self, username)
    filter:^(NSString *newName) {
        return [newName hasPrefix:@"j"];
    }]
    subscribeNext:^(NSString *newName) {
        NSLog(@"%@", newName);
    }];

 (3) combineLatest: reduce: 

// RAC() is a macro that makes the binding look nicer.
// 
// +combineLatest:reduce: takes an array of signals, executes the block with the
// latest value from each signal whenever any of them changes, and returns a new
// RACSignal that sends the return value of that block as values.

RAC(self, createEnabled) = [RACSignal  combineLatest:@[ RACObserve(self, password), RACObserve(self, passwordConfirmation) ] 
    reduce:^(NSString *password, NSString *passwordConfirm) {
        return @([passwordConfirm isEqualToString:password]);
    }];

或者:

//全部的接口處理完,再刷新
     RACSignal *performanceSingal = [RACObserve(self.viewModel, requestPerformanceFinished) distinctUntilChanged];
     RACSignal *liveDSignal = [RACObserve(self.viewModel,requestLiveDataFinished) distinctUntilChanged];
     RACSignal *needTodoSingal = [RACObserve(self.viewModel, requestNeedTodoFinished) distinctUntilChanged];
     RACSignal *quickOfficeSingal = [RACObserve(self.viewModel, requestQuickOfficeFinished) distinctUntilChanged];
    
    [[[RACSignal combineLatest:@[performanceSingal,liveDSignal,needTodoSingal,quickOfficeSingal]
                        reduce:^id(NSNumber *requestPerformanceFinished,NSNumber *requestLiveFinished,NSNumber *requestNeedTodoFinished,NSNumber *requestQuickOfficeFinished){
                            BOOL requestFinished = ([requestPerformanceFinished boolValue]
                                                    && [requestLiveFinished boolValue]
                                                    && [requestNeedTodoFinished boolValue]
                                                    && [requestQuickOfficeFinished boolValue]);
                            return @(requestFinished);
                        }] distinctUntilChanged]
     subscribeNext:^(NSNumber *finishedNumber) {
         @strongify(self);
         if([finishedNumber boolValue]){
             [self setShowLoading:NO];
             [self.tableView reloadData];
             [self refreshFinished];
         }
     }];

(4)button點擊操做

// -rac_command is an addition to UIButton. The button will send itself on that
// command whenever it's pressed.
self.button.rac_command = [[RACCommand alloc] initWithSignalBlock:^(id input) {
    NSLog(@"button was pressed!");
    return [RACSignal empty];
}];

(5)merge

// Performs NSLog() when they are both completed.
//
// +merge: takes an array of signals and returns a new RACSignal that passes
// through the values of all of the signals and completes when all of the
// signals complete.
//
// -subscribeCompleted: will execute the block when the signal completes.

[[RACSignal  merge:@[ [client fetchUserRepos], [client fetchOrgRepos] ]] 
    subscribeCompleted:^{
        NSLog(@"They're both done!");
    }];
相關文章
相關標籤/搜索