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进行连接,绑定和响应,不需要连续地观察和更新值。

举例:

摘抄:《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!");
    }];

 

 

以上是关于ReactiveCocoa学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发ReactiveCocoa学习笔记

ReactiveCocoa学习笔记

iOS学习笔记39-ReactiveCocoa入门

学习笔记:python3,代码片段(2017)

iOS 开发之 ReactiveCocoa(基础)

ReactiveCocoa