可拜讀《RAC核心元素與信號流》 html
(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];
按鈕的點擊使用action,ScrollView滾動使用delegate,屬性值改變使用KVO等系統提供的方式。這些事件,均可以經過RAC處理。blog
RAC中最核心的類RACSignal,表示未來有數據傳遞,只要有數據改變,信號內部接收到數據,就會立刻發出數據.
RAC提供signals(表現爲RACSignal)來捕捉當前以及未來的值.經過對signals進行鏈接,綁定和響應,不須要連續地觀察和更新值。
舉例:
(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!"); }];