记录RAC的使用语法糖

组合

//把多个信号聚合成你想要的信号
- (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
    */
}


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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352