美文网首页
RAC_6.终结篇

RAC_6.终结篇

作者: Iris_Fighting | 来源:发表于2018-04-04 17:32 被阅读15次

6 RAC终结篇

6.1 映射

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

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

运行如图:

image

看起来有点绕,说白了我们在什么场景下会用到这种呢?

就在我们发送的数据,需要对数据进行处理然后再订阅这个信号的时候就可以使用这种方式,其实跟我们上一节中提到的bind是一样的。

  • map

这个方法跟flattenMap稍微有一点不同,他的block返回值是一个id类型,而flattenMap是一个信号。

也就是说不用在返回信号了,直接返回一个数据,返回的数据就是处理后的数据。

    RACSubject *subject = [RACSubject subject];
    
    RACSignal *signal = [subject map:^id _Nullable(id  _Nullable value) {
        //返回的数据就是需要处理的数据
        return [NSString stringWithFormat:@"%@123",value];
    }];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    //发送数据
    [subject sendNext:@"我想静静"];

运行如图:


image

6.2 组合

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"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    //concat:按顺序组合!!
    //创建组合信号!!
    RACSignal * concatSignal = [RACSignal concat:@[signalA,signalB,signalC]];
    
    //订阅组合信号
    [concatSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

运行如图:


image

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);
    }];

运行如图:


image

merge: 无序组合,谁先发送谁先处理。

前面我说到的都是有序的,那么肯定也有无序的组合,假设我们一般页面有N多个接口的请求,需要来一个就显示一个。处理的代码呢也能写到一起。

    //创建信号
    RACSubject * signalA = [RACSubject subject];
    RACSubject * signalB = [RACSubject subject];
    RACSubject * signalC = [RACSubject subject];
    
    //组合信号
    RACSignal * mergeSignal = [RACSignal merge:@[signalA,signalB,signalC]];
    
    //订阅 -- 根据发送的情况接受数据!!
    [mergeSignal subscribeNext:^(id  _Nullable x) {
        //任意一二信号发送内容就会来这个Block
        NSLog(@"%@",x);
    }];
    
    //发送数据
    [signalC sendNext:@"数据C"];
    [signalA sendNext:@"数据A"];
    [signalB sendNext:@"数据B"];

运行如图:


image

zipWith:

两个信号压缩!只有当两个信号同时发出信号内容,并且将内容合并成为一个元祖给你

    //创建信号
    RACSubject * signalA = [RACSubject subject];
    RACSubject * signalB = [RACSubject subject];
    
    //压缩
    RACSignal * zipSignal =  [signalA zipWith:signalB];
    
    //接受数据  和发送顺序无关!!
    [zipSignal subscribeNext:^(id  _Nullable x) {
        RACTupleUnpack(NSString *str1,NSString *str2) = x;
        NSLog(@"str1=%@,str2=%@",str1,str2);
    }];
    //发送数据
    //这是一组
    [signalB sendNext:@"小明"];
    [signalA sendNext:@"小小"];
    //这也是一组
    [signalB sendNext:@"小明1"];
    [signalA sendNext:@"小小1"];
    //这也是一组
    [signalB sendNext:@"小明2"];
    [signalA sendNext:@"小小2"];

运行如图:

image

这里 只有signalAsignalB同时发送了一次信号,才会接收到信号,接收到的数据是一个元祖,值就是signalAsignalB发送的数据。

元祖的数据顺序和你发送的顺序无关,而是和[signalA zipWith:signalB]这个方法有关。

combineLatest: reduce:

组合信号,将多个信号的数据进行合并处理,在返回一个数据给新的信号。

这个东西呢,我们我们通过一个例子来说明,就拿一个简单的登录来说把。

首先呢有两个输入框(UITextField),账号和密码,还有一个按钮(UIButton),首先这个按钮是不可点击的,当两个输入框都有值的情况下呢按钮才可以点击。

 UITextField *nameTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 64, 200, 50)];
    [self.view addSubview:nameTF];
    nameTF.placeholder = @"请出入昵称";
    nameTF.backgroundColor = [UIColor yellowColor];
    
    UITextField *pwdTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 120, 200, 50)];
    [self.view addSubview:pwdTF];
    pwdTF.placeholder = @"请出入密码";
    pwdTF.backgroundColor = [UIColor grayColor];
    
    UIButton *loginBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 180, 100, 50)];
    [self.view addSubview:loginBtn];
    [loginBtn setTitle:@"登录" forState:UIControlStateNormal];
    [loginBtn setBackgroundColor:[UIColor purpleColor]];
    RACSignal *signalBtn = [loginBtn rac_signalForControlEvents:(UIControlEventTouchUpInside)];
    [signalBtn subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    //组合
    //reduceBlock参数:根据组合的信号关联的  必须一一对应!!
    RACSignal * signal = [RACSignal combineLatest:@[nameTF.rac_textSignal,pwdTF.rac_textSignal] reduce:^id _Nullable(NSString *nickName,NSString * pwd){
        
        //两个文本框的text是否有值!!
        return @(nickName.length && pwd.length);
    }];
    RAC(loginBtn,enabled) = signal;

运行如图:


image

6.3 过滤

  • filter: 当满足特定的条件,才能获取到订阅的信号数据。
    UITextField *nameTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 64, 200, 50)];
    [self.view addSubview:nameTF];
    nameTF.backgroundColor = [UIColor yellowColor];
    
    RACSignal *signal = [nameTF.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
        if (value.length > 5) {
            return YES;
        }
        return nil;
    }];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

运行如图:


image
  • ignore:忽略掉哪些值。
    UITextField *nameTF = [[UITextField alloc]initWithFrame:CGRectMake(10, 64, 200, 50)];
    [self.view addSubview:nameTF];
    nameTF.backgroundColor = [UIColor yellowColor];
    
    RACSignal *signal = [nameTF.rac_textSignal ignore:@"a"];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

运行如图:

输入第一个a并没有监听到

image
  • take: 指定拿前面的哪几条数据!!(从前往后)
    RACSubject * subject = [RACSubject subject];
    
    //take:指定拿前面的哪几条数据!!(从前往后)
    //takeLast:指定拿后面的哪几条数据!!(从后往前)注意点:一定要写结束!!
    [[subject take:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    [subject sendNext:@"2"];
    [subject sendNext:@"3"];
    [subject sendNext:@"1"];
    [subject sendCompleted];

运行如图:

image
  • 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];

运行如图:

image
  • takeUntil:直到你的标记信号发送数据的时候结束!!!
    RACSubject * subject = [RACSubject subject];
    //专门做一个标记信号!!
    RACSubject * signal = [RACSubject subject];
    
    //takeUntil:直到你的标记信号发送数据的时候结束!!!
    [[subject takeUntil:signal] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    
    [subject sendNext:@"2"];
    [subject sendNext:@"静静"];
    [signal sendNext:@"小明"];//这个信号发送之后就结束了。
//    [signal sendCompleted];//标记信号!! 这个信号发送之后也一样结束。
    
    [subject sendNext:@"3"];
    [subject sendNext:@"1"];
    [subject sendCompleted];

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

运行如图:

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

运行如图:

image

这样可以吧。。我们换个顺序好了

看图:

image
依旧是两个小明,不太靠谱吧
  • skip: 跳跃几个值
    RACSubject * subject = [RACSubject subject];
    
    //skip: 跳跃几个值
    [[subject skip:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    [subject sendNext:@"小明"];
    [subject sendNext:@"小小"];
    [subject sendNext:@"小红帽"];
    [subject sendNext:@"小爱"];
    [subject sendNext:@"小不点"];
    [subject sendNext:@"大灰狼"];

运行如图:


image

相关文章

  • RAC_6.终结篇

    6 RAC终结篇 6.1 映射 RAC的映射主要有两个方法(flattenMap map),这两个方法主要用于将信...

  • 终结篇

    文|璇子 谢那一年的初见 是你的成全 让折断的双翼 重获了新生的飞翔 谢那一年的隐忍 照顾了不懂事的情绪 只是,有...

  • 终结篇

    终于可以说再见了,对自己内心的自我说bye,如今自己流的泪都是当初脑子进的水,自己解脱自己,靠别人是不行的

  • 终结篇

    火烧云像个顽皮的小孩,把随风而动的树叶、路边大厦的玻璃和街上行人的脸颊都映得红红。 60迈的速度,兜风。 一路上,...

  • 终结篇

    我希望老脏在夜里醒来的时候,是因为做了一个噩梦,我希望他是被噩梦吓哭,最好是哭着打电话给我,然后因为吵到我睡觉被我...

  • 终结篇

    李淑敏彻夜未眠,一天又一天慢慢熬下去,她的卿不见了,成了一个82岁容颜的老头,没有一句真话,毫无一句实话,虽然...

  • 终结篇

    对于我来说,这是一种自毁。有想法,无法行动就失去了意义。即使在脑海里一步步演绎,那也并非实际,无法对现实产生影响。...

  • 命运之轮

    今天是陈一步每天一篇原创文章的第147天 时间终结妄念 黑夜终结白昼 你终结我 我终结他

  • 《长安篇》(终结篇)

    第三天本来打算去陕西历史博物馆的,可是估算错误,等我过去了,才发现这队伍不知道排的哪条街去了,大概等到天黑也...

  • 暑假终结篇

    原创作者/山水平生 我的暑假本来也就没多长,平时为了工作,只能跟家人分地而处,本想着趁难得的假期共享天伦,过几天精...

网友评论

      本文标题:RAC_6.终结篇

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