ReactiveCocoa学习笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReactiveCocoa学习笔记相关的知识,希望对你有一定的参考价值。
1. RACSignal使用步骤及底层实现
(1) 创建信号 (RACSignal底层实现:把didSubscribe保存到信号中,还不会触发。)
createSignal的意义是,创建一个signal对象,并且把参数赋值给signal的名为didSubscribe的属性,这个block的参数是subscriber,返回RACDisposable。
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe;
(2) 订阅信号,才会激活信号.
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;
RACSignal底层实现:
(2.1) subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
(2.2) subscribeNext内部会调用siganl的didSubscribe。
(使用subscribeNext订阅信号,订阅者(RACSubscriber) 订阅信号,即订阅者一旦发送了数据(三种事件:next、complete、error),就去执行回调,即subscribeNext这个block的内容。)
(3) 发送信号
- (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处理。
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!"); }];
以上是关于ReactiveCocoa学习笔记的主要内容,如果未能解决你的问题,请参考以下文章