美文网首页
记录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的使用语法糖

    组合 过滤 映射 RACCommand的用法 这里需要注意的是switchToLatest的使用 以上是比较简单的...

  • Swift语法糖的使用

    Swift语法糖的使用 语法糖的简介 语法糖Selector例子 语法糖的简介 我个人对语法糖的理解就是让你的代码...

  • Swift语法糖的使用

    Swift语法糖的使用 这个是哪里看的忘记了,反正内容不是我写的 语法糖的简介 语法糖Selector例子 语法糖...

  • vue3 语法糖setup使用keep-alive注意事项

    动态组件使用keep-alive 使用setup语法糖,定义组件TestCom2 不使用setup语法糖,定义组件...

  • 晚饭的茶真强劲

    记录一下今天踩过的坑rac使用的时候我们经常使用rac_signalForSelector 来抓代理方法. 有时候...

  • 解耦-用RAC处理网络请求

    最近接手的项目中使用了RAC,也研究学习了下,发现使用RAC确实清晰便利了许多,下面记录一下用RAC处理网络请求实...

  • python中的装饰器

    语法糖:指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。 通常来说,使用语法糖...

  • Objective-C中语法糖的趣味应用

    原文首发在ObjC语法糖 在 OC 中语法糖应用形式一般如下: 这里语法糖的使用有利于把代码集中便于阅读; 通过对...

  • IOS RAC实践

    前言 RAC使用-->IOS RAC使用 -- ReactiveObjC 本文使用RAC+MVVM来模拟用户登录 ...

  • 注册组件的语法糖写法

    1.全局注册组件语法糖 全局组件不用语法糖的构建过程:生成组件构造器 注册组件 使用组件 全局注册组件的语法糖,省...

网友评论

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

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