美文网首页
ReactiveCocoa进阶(2)

ReactiveCocoa进阶(2)

作者: 攻克乃还_ | 来源:发表于2017-09-16 21:37 被阅读7次
    所有的RACSignal都可以进行操作处理,因为所有的操作方法都定义在Stream.h中,因此只要继承了RACStream就有了操作处理的方法

    ReactiveCocoa操作思想:

    - Hook(钩子)思想:改变API(应用程序编程接口,也就是方法)执行结果
    

    一、ReactiveCocoa核心方法:bind

    • ReactiveCocoa的核心方法是bind(绑定),也是RAC的核心开发方式
    • 之前我们用的开发方式是赋值,现在我们创建对象的时候,就绑定好以后要做的事情,而不是等待赋值之后在做事情
      • 我们之前展示数据到控件上,都是重写setModel方法,而RAC在一开始创建控件时就绑定好了数据。
    • 实际开发中很少用bind方法,因为bind是RAC底层方法,而RAC已经封装了很多其他方法供我们调用
    // 需求:每次在文本框的输入后面+sun
    [[_textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{
        return ^RACSignal *(id value, BOOL *stop){
            // 信号一改变,就会执行,并且把值传递过来
            NSString *result = [NSString stringWithFormat:@"%@%@",value,@"sun"];
            return [RACReturnSignal return:result];
        };
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"获取到处理完的数据 %@",x);
    }];
    

    二、ReactiveCocoa操作方法之映射(flattenMap,map)

    • map方法是对于flattenMap方法的封装,flattenMap是对于bind方法的封装,拦截源信号的内容,改变后传出
    • map的block的返回值类型为id,flattenMap的block的返回值类型为RACSignal
      • 给订阅者发出的值不是信号,一般使用map
      • 给订阅者发出的值是信号,一般使用flatternMap
    • map的简单使用
    [[_textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        NSString *result = [NSString stringWithFormat:@"xmg %@",value];
        return result;
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    • flattenMap的简单使用
    [[_textField.rac_textSignal flattenMap:^ RACSignal * (NSString * value) {
        NSString *result = [NSString stringWithFormat:@"sun %@",value];
        return [RACReturnSignal return:result];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    • 当遇到信号中的信号时,要使用flattenMap,map结合
    [[signalOfSignals flattenMap:^RACSignal *(id value) {
        return [value map:^id _Nullable(id  _Nullable value) {
            return [NSString stringWithFormat:@"XMG:%@",value];
        }];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"1-%@",x);
    }];
    

    三、ReactiveCocoa操作方法之组合

    3.1.concat

    • [signalA concat: signalB] 把两个信号合并为一个信号,当signalA的事件完成,才能触发signalB的事件
    • 订阅后,先接收到signalA的信息,然后接收到signalB的信息
    • 方法内部直接订阅了signalA
    • 应用场景: 需要把两次请求的数据添加到一个数组,先添加A, 在添加B
    concat语法:
        // 创建信号
        RACSubject *signalA = [RACSubject subject];
        RACSubject *signalB = [RACReplaySubject subject];
        NSMutableArray *arrM = [NSMutableArray array];
        // concat
        [[signalA concat: signalB] subscribeNext:^(id  _Nullable x) {
            [arrM addObject:x];
        }];
        // 发送信号
        [signalB sendNext:@"B"];
        [signalA sendNext:@"A"];
        [signalA sendCompleted];
    

    3.2.then

    • 前面一个信号的事件完成,才能触发then后面信号的事件
    • 订阅后, 只能接收到后一个信号给订阅者的信息
    • 原理:使用concat连接then返回的信号,忽略之前信号发出的信息
    then语法:
    RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendCompleted];
        return nil;
    }];
    [[signalA then:^RACSignal * _Nonnull{
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:@2];
            return nil;
        }];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    

    3.3.merge

    • 把多个信号合并为一个信号, 任何一个信号给订阅者发送信息都能监听到
        // 无序的整合信号数据
        RACSubject *signalA = [RACSubject subject];
        RACSubject *signalB = [RACSubject subject];
        [[signalA merge:signalB] subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
        }];
        // 发送
        [signalB sendNext:@"B"];
        [signalA sendNext:@"A"];
    

    3.4.zipWith

    • 把两个个信号压缩成一个信号,只有当 两个信号都给订阅者发送数据时,才能监听到
    • 返回的x为元组
    RACSubject *signalA = [RACSubject subject];
    RACSubject *signalB = [RACSubject subject];
    [[signalA zipWith:signalB] subscribeNext:^(id  _Nullable x) {
        RACTupleUnpack(NSString *a,NSString *b) = x;
        NSLog(@"%@ %@",a,b);
     }];   
    [signalA sendNext:@"A"];
    [signalB sendNext:@"B"];
    

    3.5.combineLatest (组合)

    • 把两个信号组合成一个信号时,和zip一样
    • 把多个信号合并为一个信号,只有当 所有信号都给订阅者发送数据时,才能监听到
    • 订阅后,得到的是各个信号的最新值
    • 返回的x为元组
    [[_accountField.rac_textSignal combineLatestWith:_pwdField.rac_textSignal] subscribeNext:^(id  _Nullable x) {
        RACTupleUnpack(NSString *account,NSString *pwd) = x;
        _loginButton.enabled = account.length > 0 && pwd.length;
    }];
    

    3.6.reduce(聚合)

    • reduce后的block参数是自己写上去的。有几个信号,就写几个参数,每个参数都是信号给订阅者发送的数据
    • 底层实现:订阅聚合信号,每次有内容发出,就会执行reduce的blcok,把信号内容转换成blcok返回的值。
    • 把多个信号给订阅者发送的数据聚合到一起
    // 常见用法:先组合再聚合
    [[RACSignal combineLatest:@[_accountField.rac_textSignal,_pwdField.rac_textSignal] 
       reduce:^id (NSString *account, NSString *pwd){
       //这里返回什么,下面Block的x就是什么
       return @(account.length > 0 && pwd.length > 0);
    }] subscribeNext:^(id  _Nullable x) {
        _loginButton.enabled = [x boolValue];
    }];
    

    四、ReactiveCocoa核心操作方法-filter(过滤)

    • 减少使用if
    • 返回YES才可以给订阅者发送数据
    [[_pwdField.rac_textSignal filter:^BOOL (NSString *value) {
        // 必须要满足这个条件,才可以给订阅者发送数据
        return value.length > 6;
    }] subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@",x);
    }];
    

    五、ReactiveCocoa核心操作方法-定时器

    interval: onScheduler:

    • RACScheduler:多线程,管理多线程
    [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] 
    subscribeNext:^(NSDate * _Nullable x) {
        NSLog(@"执行了定时器");
    }];
    

    六、ReactiveCocoa核心操作方法-delay(延迟执行)

    // 延迟发送数据
    [[[RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
        [subscriber sendNext:@"hello"];
        return nil;
    }] delay:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    

    遵循NSFastEnumeration协议的可以当做数组

    相关文章

      网友评论

          本文标题:ReactiveCocoa进阶(2)

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