美文网首页iOS Developer
ReactiveCocoa 个人学习笔记记录(二)

ReactiveCocoa 个人学习笔记记录(二)

作者: 奥卡姆剃须刀 | 来源:发表于2016-11-16 01:23 被阅读62次
    WechatIMG7.jpeg

    之前就一直在看ReactiveCocoa 相关知识 但是有感觉每次看完收货甚微,且感觉零零散散 ,本blog 仅仅是记录自己的学习过程

    文章目录

    • 1 ReactiveCocoa 核心方法Bind
    • 2 ReactiveCocoa 之映射(flattenMap,Map)
      • 2-1 flattenMap和Map的区别
    • 3 ReactiveCocoa 操作方法之组合
      • 3-1 concat 按顺序的接受信号
      • 3-2 then 用于连接两个信号 当第一个信号完成 才会连接then返回的信号
      • 3-3 merge 把多个信号合并成一个信号 任何一个信号有新值的时候就会调用
      • 3-4 zipWith 把两个信号压缩成一个信号 只有当两个信号同时发出信号内容时 并且把两个信号的内容合并成一个元祖 才会触发压缩流的next事件
      • 3-5 combineLatest 将多个信号合并起来 并且拿到各个信号的最新的值 必须每个合并的signal至少都有过一次sendNext 才会触发合并的信号 和zipwith 差不多
    • 3-6 reduce(减少,降低 ,归纳) 聚合 用于信号发出的内容是元祖 把信号发出元祖的值聚合成一个值 然后通过reduce返回出来
    • 4 ReactiveCocoa 操作方法之过滤
      • 4-1 filter: 过滤信号 使用他可以获取满足条件的信号
      • 4-2 ignore 忽略某些值 的信号
      • 4-3 distinctUntilChanged 当上一次的值和当前的值不一样才会发出信号 如果两次的值一样 就不会发出信号
      • 4-4 take 取出信号 取出前几个信号
      • 4-5 takeLast 取最后N次的信号 前提条件订阅者必须调用完成 因为只有完成才知道总共有多少个信号
      • 4-6 takeUntil(RACSignal *)获取信号直到某个信号执行完成
      • 4-7 skip:(NSUInteger):跳过几个信号 不接收
    • 5 ReactiveCocoa 操作方法之秩序
      • 5-1 doNext 执行next之前会先执行这个block
      • 5-2 doComplete 执行sendComplete就会调用这个方法
    • 6 ReactiveCocoa 操作方法之时间
      • timeout: 超时 可以让一个信号在一定的时间后 自动报错
      • interval: 定时 每隔一段时间就发出信号
      • delay 延迟发送next
    • 7 ReactiveCocoa 操作方法之重复
      • retry 重试 只要失败 就一直执行信号中的block 直到成功
      • replay 重放 当一个信号被多次订阅 反复播放内容(没什么卵用)

    一 ReactiveCocoa常见操作方法介绍

    1.1 ReactiveCocoa 核心方法Bind
    • ReactiveCocoa操作的核心方法是bind(绑定),而且RAC中核心开发方式,也是绑定,之前的开发方式是赋值,而用RAC开发,应该把重心放在绑定,也就是可以在创建一个对象的时候,就绑定好以后想要做的事情,而不是等赋值之后在去做事情。

    • 列如:把数据展示到控件上,之前都是重写控件的setModel方法,用RAC就可以在一开始创建控件的时候,就绑定好数据。

    • 在开发中很少使用bind方法,bind属于RAC中的底层方法,RAC已经封装了很多好用的其他方法,底层都是调用bind,用法比bind简单.

    • bind 方法简单的介绍和使用

    // 拼接内容
    // 方式一   拿到结果后拼接内容
        [self.textFiled.rac_textSignal subscribeNext:^(id x) {
            NSLog(@"内容:%@",x);
        }];
    
    
    // 方式二  拿到结果之前 进行拼接 利用Bind方法处理
    //  处理原有信号  对信号进行加工
        // bind 方法参数  需要传入一个返回值是 RACStreamBindBlock 的参数
        // RACStreamBindBlock 是一个block类型  返回值是信号  参数是value和stop  因此参数block返回值也是一个block
                
        // RACStreamBindBlock
        // value 表示接收到信号的原始值 还没做处理
        // *stop 用来控制绑定block 如果 *stop = yes 那么就会结束绑定
        // 返回值: 信号 做好处理 在通过这个信号返回出去 一般使用RACreturnsignal,需要手动导入头文件RACReturnSignal.h
            
        // bind方法使用步骤:
        // 1 传入一个返回值为 RACStreamBindBlock 的bindblock
        // 2 描述一个RACStreamBindBlock 类型的bindblock作为block的返回值
        // 3 描述一个返回结果的信号 作为bindblock的返回值
        //  在bindblock中做信号结果的处理
        
        // 底层实现:
        // 1 源信号调用bind,会重新创建一个绑定信号。
        // 2 当绑定信号被订阅,就会调用绑定信号中的didSubscribe,生成一个bindingBlock。
        // 3 当源信号有内容发出,就会把内容传递到bindingBlock处理,调用bindingBlock(value,stop)
        // 4 调用bindingBlock(value,stop),会返回一个内容处理完成的信号(RACReturnSignal)。
        // 5 订阅RACReturnSignal,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来。
        
        [[self.textFiled.rac_textSignal bind:^RACStreamBindBlock{
                        
            return ^RACStream *(id value,BOOL *stop){
                        
                return [RACReturnSignal return:[NSString stringWithFormat:@"输出%@",value]];
                
            };
        }] subscribeNext:^(id x) {
          
            NSLog(@"%@",x);
            
        }];
    
    
    1.2 映射(flattenMap,Map)
    • 这两者主要是把源信号 内容映射成新的内容
    ----  flattenMap : 把原信号的内容映射成一个新信号 信号可以是任意的类型
    
        // flattenMap使用步骤:    
      // 1.传入一个block,block类型是返回值RACStream,参数value   
     // 2.参数value就是源信号的内容,拿到源信号的内容做处理 
     // 3.包装成RACReturnSignal信号,返回出去。
    
        [[self.textFiled.rac_textSignal flattenMap:^RACStream *(id value) {     
            
            // 原信号发出的时候就会调用block
            // block作用 : 改变原信号的内容
                    
            //  返回值  绑定信号的内容
            return [RACReturnSignal return:[NSString stringWithFormat:@"内容%@",value]];
                         
        }]subscribeNext:^(id x) {              
            NSLog(@"%@",x);
            
        }];
    
    
    ---- map: 把原信号的值映射成一个新值 
    
    //    map 的使用步骤
        // 1 传入一个block 类型是返回对象 参数是value
        // 2 value就是原信号的内容 直接拿到原信号的内容做处理
        // 3 吧处理好的内容直接返回就好了 不用包装成信号   返回的值就是映射的值
    
    
    
        [[self.textFiled.rac_textSignal map:^id(id value) {
            
            return [NSString stringWithFormat:@"内容:%@",value];
            
        }]subscribeNext:^(id x) {
          
            NSLog(@"%@",x);
        }];
    
    
    • FlatternMap 和 Map的区别

    • 1 FlatternMap 中的block返回的是信号

    • 2 Map中的block返回对象

    • 3 开发中,如果信号发出的值不是信号 映射一般使用Map

    • 4 开发中 如果信号发出的是信号 映射一般使用FlatternMap

    • signalOfSignals 信号的信号 用FlatternMap

    
        RACSubject *signalOfsignals = [RACSubject  subject];
        
        RACSubject *signal = [RACSubject subject];
        
        [[signalOfsignals flattenMap:^RACStream *(id value) {
         
            // 当signalOfsignal 的signal发发出信号才会调用
            NSLog(@"拦截%@",value);
    
            return value;        
        }] subscribeNext:^(id x) {        
            NSLog(@"内容%@",x);        
        }];
        
        // 信号的信号发送信号
        [signalOfsignals sendNext:signal];
        
        [signal sendNext:@"奥卡姆剃须刀"];
        
    
    1.3 ReactiveCocoa 操作方法值组合
    • concat 按一定顺序拼接信号 当多个信号发出的时候有顺序的接受信号
    //    按一定顺序拼接信号 当多个信号发出的时候有顺序的接受信号    
        RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
                [subscriber sendNext:@"我是一号"];
                
                [subscriber sendCompleted];
            
            return nil;
        }];
            
        RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                    
            [subscriber sendNext:@"我是二号"];
            
            [subscriber sendCompleted];
            
            return nil;
        }];
            
        RACSignal *concatSignal = [signal2 concat:signal1];
        
        //  只有第一个信号完成后 才会执行第二个信号
        [concatSignal subscribeNext:^(id x) {
            
            NSLog(@"%@",x);
            
        }];
    
    
    • then 用于连接两个信号 当第一个信号完成 才会连接then返回的信号
        RACSignal *oneSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {                
            [subscriber sendNext:@"我是信号"];        
            //  只有当第一个信号完成后 第二个信号才会执行
            [subscriber sendCompleted];        
            return nil;        
        }];    
        RACSignal *twoSignal = [oneSignal   then:^RACSignal *{        
            return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {            
                [subscriber sendNext:@"我是第二个的信号"];            
                [subscriber sendCompleted];            
                return nil;
            }];        
        }];    
        // 订阅第一个信号
        [oneSignal subscribeNext:^(id x) {
            NSLog(@"%@",x);
        }];    
        // 订阅第二个信号  只有第一个信号完成后 第二个信号发挥被触发
        [twoSignal  subscribeNext:^(id x) {                
            NSLog(@"%@",x);
        }];
    
    
    • merge 把多个信号合并成一个信号 任何一个信号有新值的时候就会调用
    
    
        // 底层实现:
        // 1.合并信号被订阅的时候,就会遍历所有信号,并且发出这些信号。
        // 2.每发出一个信号,这个信号就会被订阅
        // 3.也就是合并信号一被订阅,就会订阅里面所有的信号。
        // 4.只要有一个信号被发出就会被监听。
    
    
    RACSignal *oneSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            
            [subscriber sendNext:@"我是第一个信号"];
            
            [subscriber sendCompleted];
            
            return nil;
            
        }];
        
        RACSignal *twoSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                
                [subscriber sendNext:@"我是第二个的信号"];
                
                [subscriber sendCompleted];
                
                return nil;
        }];
    
        
        RACSignal *mergeSignal = [oneSignal merge:twoSignal];
        
        [mergeSignal subscribeNext:^(id x) {
           
            NSLog(@"%@",x);
            
        }];
        
    
    • zipWith 把两个信号压缩成一个信号 只有当两个信号同时发出信号内容时 并且把两个信号的内容合并成一个元祖 才会触发压缩流的next事件
    
        RACSignal *oneSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {                
            [subscriber sendNext:@"我是第一个信号"];        
            [subscriber sendCompleted];        
            return nil;        
        }];
        
        RACSignal *twoSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {        
            [subscriber sendNext:@"我是第二个的信号"];        
            [subscriber sendCompleted];        
            return nil;
        }];    
    
        RACSignal *zipSignal = [oneSignal zipWith:twoSignal];    
    
    //  合并出来是元祖  要想拿到元祖 要对元祖进行解包
        [zipSignal subscribeNext:^(id x) {                       
            RACTupleUnpack(id data1,id  data2) = x;        
            NSLog(@"%@---%@",data1,data2);        
        }];
        
    
    • combineLatest 将多个信号合并起来 并且拿到各个信号的最新的值 必须每个合并的signal至少都有过一次sendNext 才会触发合并的信号 和zipwith 差不多
        RACSignal *oneSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            
            [subscriber sendNext:@"我是第一个信号"];
            
            [subscriber sendCompleted];
            
            return nil;
            
        }];
        
        RACSignal *twoSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            [subscriber sendNext:@"我是第二个的信号"];
            
            [subscriber sendCompleted];
            
            return nil;
        }];
    
        
        //  必须两个都发信号 才会触发合并信号  和zipWith 一样没什么区别  也是会组装成元祖
        RACSignal *combineSignal = [oneSignal combineLatestWith:twoSignal];
        
        [combineSignal subscribeNext:^(id x) {       
            RACTupleUnpack(id data1,id data2) = x;        
            NSLog(@"%@--%@",data1,data2);        
        }];
    
    • reduce(减少,降低 ,归纳) 聚合 用于信号发出的内容是元祖 把信号发出元祖的值聚合成一个值 然后通过reduce返回出来
    
        
        RACSignal *oneSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            
            [subscriber sendNext:@"我是第一个信号"];
            
            [subscriber sendCompleted];
            
            return nil;
            
        }];
        
        RACSignal *twoSignal =  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            [subscriber sendNext:@"我是第二个的信号"];
            
            [subscriber sendCompleted];
            
            return nil;
        
        }];
        
        // 聚合
        // 常见的用法 (先组合在聚合)
        
        // combineLatee里边有多少个参数组合  后边的reduce就应该有多少个参数
        
        //  reduce 返回值是聚合之后的内容
        
        
        RACSignal *reduceSignal = [RACSignal combineLatest:@[oneSignal,twoSignal] reduce:^id(NSString *data1,NSString *data2){
            
            return [NSString stringWithFormat:@"我是数据一%@---我是数据二%@",data1,data2];
            
        }];
        
        [reduceSignal subscribeNext:^(id x) {
           
            NSLog(@"%@",x);
            
            
        }];
    
    
    1.4 ReactiveCocoa 操作方法之过滤
    • filter: 过滤信号 使用他可以获取满足条件的信号
       RACSignal *newSignal =  [self.textFiled.rac_textSignal filter:^BOOL(NSString * value) {       
            return value.length > 3;        
        }];    
    // 只有长度大于三的字符串才能被打印粗来
        [newSignal subscribeNext:^(id x) {
            NSLog(@"%@",x);
        }];
        
    
    • ignore 忽略某些值 的信号
        // 只能忽略相等的值  其他的都忽略不了 内部调用的是filter过滤
        [[self.textFiled.rac_textSignal ignore:@"123"] subscribeNext:^(id x) {       
            NSLog(@"%@",x);        
        }];
    
    • distinctUntilChanged 当上一次的值和当前的值不一样才会发出信号 如果两次的值一样 就不会发出信号
    //  只有两次数据不一样才会触发信号
        
        [[_textFiled.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {        
            NSLog(@"%@",x);        
        }];
    
    
    • take 取出信号 取出前几个信号
        // 1 创建信号
        RACSubject *signal = [RACSubject subject];
        
        // 2 处理信号 订阅信号的个数  如果订阅一个 只会接受第一个信号  subject 可以先订阅信号  在发送信号
    
        [[signal take:2] subscribeNext:^(id x) {       
            NSLog(@"%@",x);        
        }];
            
        [signal sendNext:@"1"];    
        [signal sendNext:@"2"];
    
    
    • takeLast 取最后N次的信号 前提条件订阅者必须调用完成 因为只有完成才知道总共有多少个信号
        RACSubject *signal = [RACSubject subject];
        // 取最后n次的信号    
        [[signal takeLast:2] subscribeNext:^(id x) {       
            NSLog(@"%@",x);        
        }];    
        [signal sendNext:@"1"];    
        [signal sendNext:@"2"];    
        [signal sendNext:@"3"];    
        [signal sendNext:@"4"];        
        // 必须调用完成  只用调用完成才能知道总共的信号量
        [signal sendCompleted];
    
    
    • takeUntil(RACSignal *)获取信号直到某个信号执行完成
    
        // 创建一个信号
        RACSignal *deallocSignal = [self rac_signalForSelector:@selector(viewWillDisappear:)];
        
        // 当deallocSignal信号发送的时候 就会移除通知
        [[[[NSNotificationCenter defaultCenter]rac_addObserverForName:UIKeyboardWillShowNotification object:nil] takeUntil:deallocSignal] subscribeNext:^(id x) {
            NSLog(@"键盘弹出%@",x);
        }];
    
    
    • skip:(NSUInteger):跳过几个信号 不接收
        RACSubject *signal = [RACSubject subject];
        
    //   只会接收第二个信号    
        [[signal skip:1] subscribeNext:^(id x) {       
            NSLog(@"%@",x);        
        }];        
        [signal sendNext:@"我是信号一"];    
        [signal sendNext:@"我是信号二"];
       
    
    1.5 ReactiveCocoa 操作方法之秩序
    • doNext 执行next之前会先执行这个block
    • doComplete 执行sendComplete就会调用这个方法
     
        
        [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
           
            [subscriber sendNext:@"我是奥卡姆剃须刀"];
            
            [subscriber sendCompleted];
            
            
            
            return nil;
            // 在执行订阅信号之前 会先执行这个方法
        }]doNext:^(id x) {
          
            NSLog(@"doNext--%@",x);
            
            // 信号完成后会调用这个方法
        }]doCompleted:^{
          
            NSLog(@"完成");
            
            // 订阅信号
        }] subscribeNext:^(id x) {
          
            NSLog(@"%@",x);
            
        }];
    
    
    1.6 ReactiveCocoa 操作方法之时间
    • timeout: 超时 可以让一个信号在一定的时间后 自动报错
    
        [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          
            [subscriber sendNext:@"123"];
            
            return nil;
            
            //  报错的时间是3秒
        }] timeout:3 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
                   
            NSLog(@"subscribeNext-%@",x);                
    
    // 3秒后 自动报错
        } error:^(NSError *error) {        
    
            NSLog(@"error-%@",error);        
    
        }];
    
    • interval: 定时 每隔一段时间就发出信号
        [[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
           
            NSLog(@"%@",x);
            
        }];
    
    
    • delay 延迟发送next
        [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
           
            [subscriber sendNext:@"延迟两秒钟"];
            
            return nil;
            
        }] delay:2] subscribeNext:^(id x) {
          
            NSLog(@"%@",x);
            
        }];
    
    
    1.7 ReactiveCocoa 操作方法之重复
    • retry 重试 只要失败 就一直执行信号中的block 直到成功
        __block int i = 0;
        
        [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {      
            if (i == 10) {
                [subscriber sendNext:@"123"];                        
            }else{            
                [subscriber sendError:nil];        
            }
            
            i++;
            
            return nil;
            
        }] retry ] subscribeNext:^(id x) {
           
            NSLog(@"subscribeNext--%@",x);
            
        }error:^(NSError *error) {
          
            NSLog(@"error--%@",error);
            
        }];
    
    
    • replay 重放 当一个信号被多次订阅 反复播放内容(没什么卵用)
        
        RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            [subscriber sendNext:@"123"];
            
            [subscriber sendNext:@"456"];
            
            return nil;
        }]replay];
       
        [signal subscribeNext:^(id x) {       
            NSLog(@"%@",x);        
        }];
        
        [signal subscribeNext:^(id x) {
            NSLog(@"%@",x);
        }];
        
    

    相关文章

      网友评论

        本文标题:ReactiveCocoa 个人学习笔记记录(二)

        本文链接:https://www.haomeiwen.com/subject/rcglpttx.html