zoukankan      html  css  js  c++  java
  • RAC中常见的高级用法-组合

    • 组合:
    concat组合:
              按一定顺序执行皇上与皇太子关系
    concat底层实现:
        1.当拼接信号被订阅,就会调用拼接信号的didSubscribe
        2.didSubscribe中会先订阅第一个源信号(signalA)
        3.会执行第一个源信号(signalA)的didSubscribe
        4.第一个源信号(signalA)didSubscribe中发送值,就会调用第一个源信号(signalA)订阅者的nextBlock,通过拼接信号的订阅者把值发送出来.
        5.第一个源信号(signalA)didSubscribe中发送完成,就会调用第一个源信号(signalA)订阅者的completedBlock,订阅第二个源信号(signalB)这时候才激活(signalB)。
        6.订阅第二个源信号(signalB),执行第二个源信号(signalB)的didSubscribe
        7.第二个源信号(signalA)didSubscribe中发送值,就会通过拼接信号的订阅者把值发送出来.
    - (void)concat
    {
        //创建信号A
        RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            //发送请求
            NSLog(@"发送上部分的请求");
            //发送信号
            [subscriber sendNext:@"上部分数据"];
            //发送完毕
            //加上后就可以上部分发送完毕后发送下半部分信号
            [subscriber sendCompleted];
            return nil;    
        }];
       
        //创建信号B
        RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            //发送请求
            NSLog(@"发送下部分的请求");
            //发送信号
            [subscriber sendNext:@"下部分数据"];
            return nil;   
        }];
        //创建组合信号
        //concat:按顺序去连接(组合)
        //注意:第一个信号必须调用sendCompleted
        RACSignal *concat = [signalA concat:signalB];
        //订阅组合信号
        [concat subscribeNext:^(id x) {
            //既能拿到A信号的值,又能拿到B信号的值
            NSLog(@"%@", x);
        }];
    }
     
    then:
         用于连接两个信号,当第一个信号完成,才会连接then返回的信号
         注意: 使用then之前的信号的值会被忽略掉.
    底层实现:
        1、先过滤掉之前的信号发出的值。
        2.使用concat连接then返回的信号
    - (void)then
    {
        //创建信号A
        RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            //发送请求
            NSLog(@"发送上部分的请求");
            //发送信号
            [subscriber sendNext:@"上部分数据"];
            //发送完毕
            //加上后就可以上部分发送完毕后发送下半部分信号
            [subscriber sendCompleted];
            return nil;
           
        }];
       
        //创建信号B
        RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            //发送请求
            NSLog(@"发送下部分的请求");
            //发送信号
            [subscriber sendNext:@"下部分数据"];
            return nil;
           
        }];
       
        //thenSignal组合信号
        //then:会忽略掉第一个信号的所有值
        RACSignal *thenSignal = [signalA then:^RACSignal *{
            //返回的信号就是需要组合的信号
            return signalB;
        }];
        //订阅信号
        [thenSignal subscribeNext:^(id x) {
            NSLog(@"%@", x);
        }];
       
        /*
         结果:
         发送上部分的请求
         发送下部分的请求
         下部分数据
         */
    }
     
    merge
         把多个信号合并为一个信号,任何一个信号有新值的时候就会调用,没有顺序
    - (void)merge
    {
        //创建信号A
        RACSubject *signalA = [RACSubject subject];
        //创建信号B
        RACSubject *signalB = [RACSubject subject];
       
        //组合信号
        RACSignal *mergeSignal = [signalA merge:signalB];
       
        //订阅信号
        [mergeSignal subscribeNext:^(id x) {
            //任意一个信号发送内容都会来到这个block
            NSLog(@"%@", x);
        }];
       
        //发送数据
        [signalB sendNext:@"下部分"];
        [signalA sendNext:@"上部分"];
        /*结果:下部分上部分*/
    }
     
    zipWith: 等所有信号都发送内容的时候才会调用(夫妻关系)
         把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件
    底层实现:
        1.定义压缩信号,内部就会自动订阅signalA,signalB
        2.每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出。
    - (void)zipWith
    {
        //创建信号A
        RACSubject *signalA = [RACSubject subject];
        //创建信号B
        RACSubject *signalB = [RACSubject subject];
        //压缩成一个信号
        //当一个界面多个请求时,要等所有的请求都完成才能更新UI
        //打印顺序跟组合顺序有关,跟发送顺序无关
        RACSignal *zipSignal = [signalA zipWith:signalB];
        //订阅信号
        [zipSignal subscribeNext:^(id x) {
            NSLog(@"%@", x);
        }];
        //发送信号
        [signalA sendNext:@"HMJ"];
        [signalB sendNext:@"GQ"];
    /*
     结果
     <RACTuple: 0x7ffd8351f120>
     (
        HMJ,
        GQ
     )
     */
    }
     
    combineLatest:
         将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号。
    底层实现:
        1.当组合信号被订阅,内部会自动订阅signalA,signalB,必须两个信号都发出内容,才会被触发。
        2.并且把两个信号组合成元组发出。
    - (void)combineLatest
    {
        RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [subscriber sendNext:@"A"];
            return nil;
        }];
        RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [subscriber sendNext:@"B"];
            return nil;
        }];
        //把两个信号组合成一个信号
        RACSignal *combineSignal = [signalA combineLatestWith:signalB];
        //订阅组合信号
        [combineSignal subscribeNext:^(id x) {
            NSLog(@"%@", x);
        }];
    }
     
    reduce聚合:用于信号发出的内容是元组,把信号发出元组的值聚合成一个值
         常见的用法(先组合在聚合)。combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock
    reduce中的block简介:
        reduceblcok中的参数,有多少信号组合,reduceblcok就有多少参数,每个参数就是之前信号发出的内容
        reduceblcok的返回值:聚合信号之后的内容。
    底层实现:
        订阅聚合信号,每次有内容发出,就会执行reduceblcok,把信号内容转换成reduceblcok返回的值。
    - (void)combineLatestWithReduce
    {
        /*登录界面:两个文本框(账户,密码) + 一个登录按钮*/
       
        //组合多个信号
        //reduce:聚合
        //reduceBlock的参数与组合的信号一一对应,可以在reduce:后拿到信号的值
        RACSignal *combineSignal = [RACSignal combineLatest:@[_accountName.rac_textSignal, _passWord.rac_textSignal] reduce:^id(NSString *account, NSString *pwd){
            //block:只要源信号发送内容就会调用,组合成新的一个值
            //聚合的值就是组合信号的内容
            return @(account.length && pwd.length);
        }];
        //订阅信号
        //    [combineSignal subscribeNext:^(id x) {
        //        self.loginBtn.enabled = [x boolValue];
        //
        //    }];
        //等同于
        RAC(self.loginBtn, enabled) = combineSignal;
    }
  • 相关阅读:
    nginx访问控制
    nginx的请求限制
    nginx目录及配置语法
    安装Nginx
    Docker Service启动时挂载docker命令
    禁止flyme自动下载rom
    docker.service 修改指南
    debian 10.x (buster) 离线安装docker及卸载
    按照容器名称清除docker容器产生的日志文件内容
    debian修改系统语言为英文
  • 原文地址:https://www.cnblogs.com/HMJ-29/p/4943997.html
Copyright © 2011-2022 走看看