美文网首页RACRAC实战
ReactiveCocoa入门学习四(映射,组合,过滤)

ReactiveCocoa入门学习四(映射,组合,过滤)

作者: Maple_Xu | 来源:发表于2017-05-03 14:07 被阅读23次

    RAC映射

    RAC的映射主要有两个方法(flattenMap map),这两个方法主要用于将信号源的内容映射成为一个新的信号。

    • flattenMap:它其实也是绑定信号,一般用于信号中的信号。
        //创建信号
        RACSubject * subject = [RACSubject subject];
        
        //绑定信号
        RACSignal * bindSignal = [subject flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
            //block:只要源信号发送内容就会调用
            //value:就是源信号发送的内容
            value = [NSString stringWithFormat:@"处理数据:%@",value];
            
            //返回信号用来包装修改过的内容
            return [RACReturnSignal return:value];
        }];
        
        //订阅绑定信号
        [bindSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        //发送数据
        [subject sendNext:@"123"];
    

    看起来有点绕,说白了我们在什么场景下会用到这种呢?就在我们发送的数据,需要对数据进行处理然后再订阅这个信号的时候就可以使用这种方式,其实跟我们上一节中提到的 bind 是一样的。

    flattenMap一般用于处理信号中的信号。

        RACSubject * signalOfSignal = [RACSubject subject];
        RACSubject * signal = [RACSubject subject];
      
        [[signalOfSignal flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
            return value;
        }] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
    
        //发送信号
        [signalOfSignal sendNext:signal];
        [signal sendNext:@"123"];
    
    
    • map:这个方法呢 跟flattenMap稍微有一点不同,他的block返回值是一个id类型,而flattenMap是一个信号。也就是说不用在返回信号了,直接返回一个数据,返回的数据就是处理后的数据。
        //创建信号
        RACSubject * subject = [RACSubject subject];
        
        //绑定
        [[subject map:^id _Nullable(id  _Nullable value) {
            //返回的数据就是需要处理的数据
            return [NSString stringWithFormat:@"处理数据%@",value];
        }] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        //发送数据
        [subject sendNext:@"123"];
    

    RAC组合

    • concat:按顺序组合。
      在上一篇中我们说到了 rac_liftSelector 的使用场景,它是在等多个信号全部都返回数据后再刷新UI。那么我们现在有一个需求,就是按顺序刷新UI,也就是说你这些接口什么时候请求完数据我并不知道,但是你请求完成后的处理要按照我的顺序来。处理完第一个,再处理第二个。
        //组合!!
        //创建信号!!
        RACSignal * signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"发送请求A");
            //发送数据
            [subscriber sendNext:@"数据A"];
            //哥么结束了!!
            [subscriber sendCompleted];
            //[subscriber sendError:nil];
            return nil;
        }];
        
        RACSignal * signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"发送请求B");
            //发送数据
            [subscriber sendNext:@"数据B"];
            [subscriber sendCompleted];
            return nil;
        }];
        
        RACSignal * signalC = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"发送请求C");
            //发送数据
            [subscriber sendNext:@"数据C"];
            return nil;
        }];
        
        //concat:按顺序组合!!
        //创建组合信号!!
        //RACSignal * concatSignal = [[signalA concat:signalB] concat:signalC];
        RACSignal * concatSignal = [RACSignal concat:@[signalA,signalB,signalC]];
        
        //订阅组合信号
        [concatSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
    
    • then:忽略掉前面一个信号所有的值,返回后一个信号的数据。也就是说后一个信号的数据要依赖前一个信号的发送完毕,但我并不需要处理前一个信号的数据。
        //创建信号!!
        RACSignal * signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"发送请求A");
            //发送数据
            [subscriber sendNext:@"数据A"];
            [subscriber sendCompleted];
            return nil;
        }];
        
        RACSignal * signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"发送请求B");
            //发送数据
            [subscriber sendNext:@"数据B"];
            [subscriber sendCompleted];
            return nil;
        }];
        
        //then:忽略掉第一个信号所有的值!!
        RACSignal * thenSignal = [signalA then:^RACSignal * _Nonnull{
            return signalB;
        }];
        
        //订阅信号
        [thenSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
    
    • merge:无序组合,谁先发送谁先处理。
      前面我说到的都是有序的,那么肯定也有无序的组合,假设我们一般页面有N多个接口的请求,需要来一个就显示一个。处理的代码呢也能写到一起。
        //创建信号
        RACSubject * signalA = [RACSubject subject];
        RACSubject * signalB = [RACSubject subject];
        RACSubject * signalC = [RACSubject subject];
        
        //组合信号
        //RACSignal * mergeSignal = [signalA merge:signalB];
        RACSignal * mergeSignal = [RACSignal merge:@[signalA,signalB,signalC]];
        
        //订阅 -- 根据发送的情况接受数据!!
        [mergeSignal subscribeNext:^(id  _Nullable x) {
            //任意一二信号发送内容就会来这个Block
            NSLog(@"%@",x);
        }];
        
        //发送数据
        [signalC sendNext:@"数据C"];
        [signalA sendNext:@"数据A"];
        [signalB sendNext:@"数据B"];
    
    • zipWith:两个信号压缩!只有当两个信号同时发出信号内容,并且将内容合并成为一个元祖给你
        //创建信号
        RACSubject * signalA = [RACSubject subject];
        RACSubject * signalB = [RACSubject subject];
        
        //压缩
        RACSignal * zipSignal =  [signalA zipWith:signalB];
        
        //接受数据  和发送顺序无关!!
        [zipSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        //发送数据
        //这是一组
        [signalB sendNext:@"B"];
        [signalA sendNext:@"A"];
        //这也是一组
        [signalB sendNext:@"B1"];
        [signalA sendNext:@"A1"];
        //这也是一组
        [signalB sendNext:@"B2"];
        [signalA sendNext:@"A2"];
    

    这里 只有signalA、signalB同时发送了一次信号,才会接收到信号,接收到的数据是一个元祖,值就是signalA、signalB发送的数据。元祖的数据顺序和你发送的顺序无关,而是和[signalA zipWith:signalB]这个方法有关。

    • combineLatest: reduce: 组合信号,将多个信号的数据进行合并处理,在返回一个数据给新的信号。
      这个东西呢,我们我们通过一个例子来说明,就拿一个简单的登录来说把。首先呢有两个输入框(UITextField),账号和密码,还有一个按钮(UIButton),首先这个按钮是不可点击的,当两个输入框都有值的情况下呢按钮才可以点击。
        //组合
        //reduceBlock参数:根据组合的信号关联的  必须 一一对应!!
        RACSignal * signal = [RACSignal combineLatest:@[_accountFiled.rac_textSignal,_pwdFiled.rac_textSignal] reduce:^id _Nullable(NSString * account,NSString * pwd){
            
            //两个文本框的text是否有值!!
            return @(account.length && pwd.length);
        }];
        RAC(_loginBtn,enabled) = signal;
    

    这样来看,就不难理解了吧。

    RAC过滤

    • filter:当满足特定的条件,才能获取到订阅的信号数据。
        [[_textfiled.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
            //value:源信号的内容
            return [value length] > 5;
            //返回值:就是过滤条件,只有满足这个条件,才能获取到内容
        }] subscribeNext:^(NSString * _Nullable x) {
            NSLog(@"%@",x);
        }];
    
    • ignore:忽略掉哪些值。
        RACSubject * subject = [RACSubject subject];
        
        //忽略一些值!!
        RACSignal * ignoreSignal = [[[subject ignore:@"1"] ignore:@"2"] ignore:@"3"];
        
        //订阅
        [ignoreSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        //发送数据
        [subject sendNext:@"1"];
        [subject sendNext:@"2"];
        [subject sendNext:@"13"];
        [subject sendNext:@"3"];
    

    这里 1 2 3 就被忽略掉了,所以打印的就是13。

    • take:指定拿前面的哪几条数据!!(从前往后)
    • takeLast:指定拿后面的哪几条数据!!(从后往前)注意点:一定要写结束!!
        RACSubject * subject = [RACSubject subject];
        
        //take:指定拿前面的哪几条数据!!(从前往后)
        //takeLast:指定拿后面的哪几条数据!!(从后往前)注意点:一定要写结束!!
        [[subject takeLast:2] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        [subject sendNext:@"2"];
        [subject sendNext:@"3"];
        [subject sendNext:@"1"];
        [subject sendCompleted];
    
    • takeUntil:直到你的标记信号发送数据的时候结束!!!
        RACSubject * subject = [RACSubject subject];
        //专门做一个标记信号!!
        RACSubject * signal = [RACSubject subject];
        
        //takeUntil:直到你的标记信号发送数据的时候结束!!!
        [[subject takeUntil:signal] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        
        [subject sendNext:@"2"];
        
        //[signal sendNext:@".."];//这个信号发送之后就结束了。
        [signal sendCompleted];//标记信号!! 这个信号发送之后也一样结束。
        
        [subject sendNext:@"3"];
        [subject sendNext:@"1"];
        [subject sendCompleted];
    

    当signal发送信号后,subject的发送就会结束,这里的 3 1 就不会在发送了。这种方式也比较常用。

    • distinct:忽略掉重复数据
        //1.创建信号
        RACSubject * subject = [RACSubject subject];
        
        //忽略掉重复数据
        [[subject distinctUntilChanged] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        
        //发送
        [subject sendNext:@"1"];
        [subject sendNext:@"1"];
        [subject sendNext:@"2"];
        [subject sendNext:@"2"];
    

    这里 有 1 2 都有重复的,所以这里只会打印 1 2。

    • skip: 跳跃几个值
        RACSubject * subject = [RACSubject subject];
        
        //skip: 跳跃几个值
        [[subject skip:2] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
    
        [subject sendNext:@"1"];
        [subject sendNext:@"2"];
        [subject sendNext:@"3"];
    

    这里就跳过了 1 2 ,所以只能打印 3。

    相关文章

      网友评论

        本文标题:ReactiveCocoa入门学习四(映射,组合,过滤)

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