美文网首页
记录RAC的使用语法糖

记录RAC的使用语法糖

作者: Hflydragon | 来源:发表于2020-06-01 18:23 被阅读0次

    组合

    //把多个信号聚合成你想要的信号
    - (void)loadTestData
    {
        RACSignal *combinSignal = [RACSignal combineLatest:@[self.userName.rac_textSignal,self.password.rac_textSignal] reduce:^id(NSString *account, NSString *pwd){
            //reduce里的参数一定要和数组里的元素一一对应起来
            //block: 只要源信号发送内容,就会调用,组合成一个新值。
            return @(account.length && pwd.length);
        }];
        
        RAC(self.loginBtn,enabled) = combinSignal;
    }
    
    - (void)zipWith
    {
        // zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元祖,才会触发压缩流的next事件
        
        // 创建信号A
        RACSubject *signalA = [RACSubject subject];
        // 创建信号B
        RACSubject *signalB = [RACSubject subject];
        // 压缩成一个信号
        // **-zipWith-** :当一个界面多个请求的时候,要等所有的请求完成才更新UI
        RACSignal *zipSignal = [signalA zipWith:signalB];
        [zipSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);//所有的值将会被包装成元祖
        }];
        
        //发送信号 交互顺序,元祖内的元素的顺序是不会变的,跟发送的顺序无关,而是跟压缩的顺序有关
        [signalA sendNext:@(1)];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [signalB sendNext:@(2)];
        });
        
    }
    
    
    /// 任何一个信号请求完成都会被订阅到
    /// merge: 多个信号合并成一个信号,任何一个信号有新值都会调用
    - (void)merge {
        // 创建信号A
        RACSubject *signalA = [RACSubject subject];
        // 创建信号B
        RACSubject *signalB = [RACSubject subject];
        // 合并信号
        RACSignal *merge = [signalA merge:signalB];
        //订阅信号
        [merge subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        // 发送信号
        [signalB sendNext:@"下部分更新"];
        [signalA sendNext:@"上部分更新"];
        
        /**
            2020-06-01 15:28:07.725 RACUserful[9883:197270] 下部分更新
            2020-06-01 15:28:07.726 RACUserful[9883:197270] 上部分更新
         */
    }
    
    
    /// then -- 使用需求:有两部分数据:想让上部分先进行网络请求但是过滤掉数据,然后进行下部分的,拿到部分数据
    - (void)then {
        RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"--------发送上部分请求---------afn");
            [subscriber sendNext:@"上部分数据"];
            [subscriber sendCompleted];//必须调用sendCompleted方法
            return nil;
        }];
        
        RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"--------发送下部分请求---------afn");
            [subscriber sendNext:@"下部分数据"];
            return nil;
        }];
        
        //then将会忽略掉第一个信号的所有值
        //注意 第一个信号必须要调用 sendComplented
        RACSignal *thenSignal = [signalA then:^RACSignal * _Nonnull{
            return signalB;
        }];
        
        [thenSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        /**
            2020-06-01 15:44:32.806 RACUserful[9883:197270] --------发送上部分请求---------afn
            2020-06-01 15:44:32.806 RACUserful[9883:197270] --------发送下部分请求---------afn
            2020-06-01 15:44:32.806 RACUserful[9883:197270] 下部分数据
         */
    }
    
    
    
    /// concat --- 使用需求:有两部分数据,想让上部分先执行,完了之后再让下部分执行 (都可以获得值)
    - (void)concat {
        RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"--------发送上部分请求---------afn");
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [subscriber sendNext:@"上部分数据1"];//必须调用sendCompleted方法
                [subscriber sendCompleted];
            });        
            return nil;
        }];
        
        RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"--------发送下部分请求---------afn");
            [subscriber sendNext:@"下部分数据"];
            return nil;
        }];
        
        //then将会忽略掉第一个信号的所有值
        //注意 第一个信号必须要调用 sendComplented
        RACSignal *concatSignal = [signalA concat:signalB];
        
        [concatSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        /**
         
            2020-06-01 15:53:02.208 RACUserful[9883:197270] --------发送上部分请求---------afn
            2020-06-01 15:53:02.208 RACUserful[9883:197270] 上部分数据
            2020-06-01 15:53:02.209 RACUserful[9883:197270] --------发送下部分请求---------afn
            2020-06-01 15:53:02.209 RACUserful[9883:197270] 下部分数据
         */
    }
    

    过滤

    
    
    /// 跳跃:skip传入2 跳过前面两个值
    /// 实际用途:在实际开发中,后台返回的数据前几个没用,想跳过就直接skip
    - (void)skip {
        
        //1.
        RACSubject *subject = [RACSubject subject];
        [[subject skip:2] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        [subject sendNext:@1];
        [subject sendNext:@2];
        [subject sendNext:@3];
        
        //2.
        
        RACSignal *singal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:@4];
            [subscriber sendNext:@5];
            [subscriber sendNext:@6];
            return nil;
        }];
        [[singal skip:1] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        /**
         2020-06-01 11:08:04.294 RACUserful[4450:86732] 3
         2020-06-01 11:08:04.295 RACUserful[4450:86732] 5
         2020-06-01 11:08:04.295 RACUserful[4450:86732] 6
         */
    }
    
    /// distinctUntilChanged : -如果当前的值跟上一次的值一样,就不会被订阅到,很实用
    - (void)distinctUntilChanged {
        RACSubject *subject = [RACSubject subject];
        [[subject distinctUntilChanged] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        [subject sendNext:@{
            @"title":@"name",
            @"vale":@"1"
        }];
        [subject sendNext:@{
            @"title":@"name",
            @"vale":@"2"
        }];
        [subject sendNext:@{
            @"title":@"name",
            @"vale":@"2"
        }];
        [subject sendNext:@3];
        
        /**
                2020-06-01 11:14:36.511 RACUserful[4450:86732] {
                    title = name;
                    vale = 1;
                }
                2020-06-01 11:14:36.511 RACUserful[4450:86732] {
                    title = name;
                    vale = 2;
                }
                2020-06-01 11:14:36.511 RACUserful[4450:86732] 3
         */
    }
    
    
    /// take: 可以屏蔽一些值,去前面几个值
    - (void)take {
        RACSubject *sub = [RACSubject subject];
        
        [[sub take:2] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        [sub sendNext:@1];
        [sub sendNext:@2];
        [sub sendNext:@3];
        
        /**
            2020-06-01 11:24:55.845053+0800 RACUserful[5331:99724] 1
            2020-06-01 11:24:55.845256+0800 RACUserful[5331:99724] 2
         */
    }
    
    
    /// 这里的takeLast 和 take一样,也是截取,不过是倒序,从最后开始数
    /// 注意这里的takeLast 使用时必须调用 complented ,这样才能确定最后值
    - (void)takeLast
    {
        RACSubject *sub = [RACSubject subject];
        [[sub takeLast:2] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        [sub sendNext:@1];
        [sub sendNext:@2];
        [sub sendNext:@3];
        [sub sendCompleted];
        
        /**
            2020-06-01 11:27:01.145 RACUserful[5331:99724] 2
            2020-06-01 11:27:01.146 RACUserful[5331:99724] 3
         */
    }
    
    
    /// takeUntil : 给 takeUntil 传递的是哪个信号,那么当这个信号发送信号或者sendComplented,就不能再接受源信号的内容了
    - (void)takeUntil {
        
        RACSubject *sub1 = [RACSubject subject];
        RACSubject *sub2 = [RACSubject subject];
        
        [[sub1 takeUntil:sub2] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        //注意:谁takeUntil谁终止,并不会影响作为条件的sub2
        /**
            [sub2 subscribeNext:^(id  _Nullable x) {
                NSLog(@"sub2---%@",x);
            }];
         */
        
        [sub1 sendNext:@"1"];
        [sub2 sendNext:@"2"];
        [sub1 sendNext:@"3"];
        
        /**
            2020-06-01 11:30:38.926 RACUserful[5331:99724] 1
         */
    }
    
    ///忽略掉一些值
    - (void)ignore {
        // ignore:忽略一些值
        // ignoreValues:表示忽略所有的值
        // 1.创建信号
        RACSubject *subject = [RACSubject subject];
        
        // 2. 忽略一些值
        RACSignal *ignoreSignal = [subject ignore:@2];
        
        // 3. 订阅信号
        [ignoreSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        [subject sendNext:@2];
    }
    
    

    映射

    
    //遍历绑定
    - (void)loadTestData
    {
        //创建信号
        RACSubject *subject = [RACSubject subject];
        //绑定信号
        RACSignal *bindSingal = [subject map:^id _Nullable(id  _Nullable value) {
           //返回的类型就是你需要映射的值
            return [NSString stringWithFormat:@"ws:%@",value];//这里将源信号发送给123,前面拼接ws
        }];
        //订阅绑定信号
        [bindSingal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        //发送信号
        [subject sendNext:@"123"];
    }
    
    - (void)filterMap {
    
        //创建信号
        RACSubject *subject = [RACSubject subject];
        //绑定信号
        RACSignal *bindSingal = [subject flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
            //block:只要源信号发送内容就会调用
            //value:就是源信号发送的内容
            //返回信号用于包装成修改内容的值
            return [RACReturnSignal return:@([value intValue]+2)];
        }];
        //订阅绑定信号
        //flattenMap中返回的是什么信号,订阅的就是什么信号(那么,x的值等于value的值,如果我们操作value的值,x也会随之改变)
        [bindSingal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        //发送信号
        [subject sendNext:@"123"];
    }
    
    
    - (void)filterMap2{
        // flattenMap 主要用于信号中的信号
        // 创建信号
        RACSubject *signalofSignals = [RACSubject subject];
        RACSubject *signal = [RACSubject subject];
        
        //订阅信号,这里之前用sendNext和 switchToLatest 的方式,这次不再使用老方法
        //方法一
    //    RACSignal *bindSignal = [signalofSignals flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
    //        return value;
    //    }];
    //    [bindSignal subscribeNext:^(id  _Nullable x) {
    //        NSLog(@"%@",x);
    //    }];
        
        
        //方法二----开发中常用的 ,就是合并方法一
        [[signalofSignals flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
            return value;
        }] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        [signalofSignals sendNext:signal];
        [signal sendNext:@"456"];
        
    }
    
    

    RACCommand的用法

    
    /// 普通做法
    - (void)loadTestData1
    {
        //不能返回空的信号
        //1.创建命令
        RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
            // block调用,执行命令的时候传进来的参数
            NSLog(@"%@",input);
            
            //返回值不允许为nil
            return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
                //模拟数据
                [subscriber sendNext:@"执行命令所产生的数据"];
                return nil;
            }];
        }];
        
        //执行命令
        RACSignal *signal = [command execute:@2];// 这里其实用到的是replaySubject 可以先发送命令再订阅,大致原理如此
        
        //如何拿到执行命令后产生的数据
        //1.订阅执行命令返回的信号
        
        //订阅信号
        [signal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        /**
            2020-06-01 09:51:46.519 RACUserful[2079:44351] 2
            2020-06-01 09:51:46.529 RACUserful[2079:44351] 执行命令所产生的数据
         */
    }
    
    /// 一般做法
    - (void)loadTestData2
    {
       RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
           //执行订阅,这里的input为传递进来的参数
           NSLog(@"%@",input);
           return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
               NSLog(@"执行命令所产生的数据");
               [subscriber sendNext:@1];
               return nil;
           }];
        }];
        
        //方式二:
        //订阅信号,这里的必须先订阅才能发送命令
        //executionSignals代表信号源,信号中信号
        [command.executionSignals subscribeNext:^(RACSignal *x) {
            NSLog(@"%@",x);
            [x subscribeNext:^(id  _Nullable y) {
                NSLog(@"%@",y);
            }];
        }];
        
        [command execute:@2];
        
        /**
            2020-06-01 09:52:55.595 RACUserful[2079:44351] 2
            2020-06-01 09:52:55.604 RACUserful[2079:44351] <RACDynamicSignal: 0x6000026114c0> name:
            2020-06-01 09:52:55.604 RACUserful[2079:44351] 执行命令所产生的数据
            2020-06-01 09:52:55.604 RACUserful[2079:44351] 1
         */
    }
    
    - (void)loadTestData3
    {
       RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
            //执行订阅,这里的input为传递进来的参数
            NSLog(@"%@",input);
            return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
                [subscriber sendNext:@"执行命令所产生的数据"];
                return nil;
            }];
        }];
        // 方式三
        // switchToLatest获取最新发送的信号,只能用于信号中信号。
        [command.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        [command execute:@3];
        
        /**
            2020-06-01 09:50:03.527968+0800 RACUserful[2079:44351] 3
            2020-06-01 09:50:03.555969+0800 RACUserful[2079:44351] 执行命令所产生的数据
         */
    }
    
    /// 监听事件有没有完成
    - (void)loadTestData5
    {
        //注意:当前命令内部发送数据完成,一定要主动发送完成
        RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
            //执行订阅,这里的input为传递进来的参数
            NSLog(@"%@",input);
            return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
                [subscriber sendNext:@"执行命令所产生的数据"];
                
                // 发送完成
                [subscriber sendCompleted];
                return nil;
            }];
        }];
        
        // 监听事件是否已经完成
        [command.executing subscribeNext:^(NSNumber * _Nullable x) {
            if([x boolValue] == YES){
                NSLog(@"当前正在执行 %@",x);
            }else{
                NSLog(@"没有执行或者执行完成");
            }
        }];
        
        [command execute:@5];
    }
    
    
    

    这里需要注意的是switchToLatest的使用

    
    
    ///switchToLatest用法
    - (void)loadTestData4
    {
        //创建信号中的信号
        RACSubject *singalOfsingals = [RACSubject subject];
        RACSubject *singalA = [RACSubject subject];
        //switchToLatest 获取信号中信号发送的最新信号
        [singalOfsingals.switchToLatest subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
    
        [singalOfsingals sendNext:singalA];
        [singalA sendNext:@4];
        
        /**
         以上写法等价于
            [singalOfsingals subscribeNext:^(id  _Nullable x) {
                [x subscribeNext:^(id  _Nullable y) {
                    NSLog(@"%@",y);
                }];
            }];
             
            [singalOfsingals sendNext:singalA];
            [singalA sendNext:@4];
         
            2020-06-01 09:56:36.470 RACUserful[2079:44351] 4
        */
    }
    
    
    

    以上是比较简单的语法糖,适用常见的一些场景。

    相关文章

      网友评论

          本文标题:记录RAC的使用语法糖

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