美文网首页iOS 进阶ios基础
2、关于ReactiveObjC原理及流程简介

2、关于ReactiveObjC原理及流程简介

作者: 披萨配可乐 | 来源:发表于2018-01-16 19:31 被阅读454次

    本文是对ReactiveObjC原理简介

    一、流程分析

    ReactiveObjC主要有三个关键类:
    1、RACSignal 信号
    RACSignal 是各种信号的基类,其中RACDynamicSignal是用的最多的动态信号

    2、RACSubscriber 订阅者
    RACSubscriber是实现了RACSubscriber协议的订阅者类,这个协议定义了4个必须实现的方法

    @protocol RACSubscriber <NSObject>
    @required
    - (void)sendNext:(nullable id)value;              //常见
    - (void)sendError:(nullable NSError *)error;  //常见
    - (void)sendCompleted;                                //常见
    - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;
    @end
    

    RACSubscriber主要保存了三个block,跟三个常见的协议方法一一对应

    @property (nonatomic, copy) void (^next)(id value);
    @property (nonatomic, copy) void (^error)(NSError *error);
    @property (nonatomic, copy) void (^completed)(void);
    

    3、RACDisposable 清洁工
    RACDisposable 主要是对资源的释放处理,其中使用RACDynamicSignal时,会创建一个RACCompoundDisposable管理清洁工对象。其内部定义了两个数组,一个是_inlineDisposables[2]固定长度2的A fast array,超出2个对象的长度由_disposables数组管理,_inlineDisposables数组速度快,两个数组都是线程安全的。

    4、简单信号调用流程

    结合以下代码分析

    //1、创建信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        //任何时候,都可以发送信号,可以异步
        [subscriber sendNext:@"发送信号"];
        [subscriber sendCompleted];
        return nil;
    }];
        
    //2、订阅信号
    [signal subscribeNext:^(id  _Nullable x) {
         //收到信号时
         NSLog(@"信号内容:%@", x);
    }];
    

    调用流程如下:


    流程.png
    注意:如果didSubscribe是异步执行,则会先返回RACDisposable,然后执行sendNext:

    二、主要类分析

    关于ReactiveObjC所有class的继承关系

    ReactiveObjC.png
    图片来自(http://www.cnblogs.com/CoderEYLee/p/Object-C-0010.html)[http://www.cnblogs.com/CoderEYLee/p/Object-C-0010.html]
    1、RACStream

    RACStream是所有信号类的父类,也是一个抽象类。它定义了五个子类必须实现的方法:

    + (__kindof RACStream<ValueType> *)empty;
    + (__kindof RACStream<ValueType> *)return:(nullable ValueType)value;
    - (__kindof RACStream *)bind:(RACStreamBindBlock (^)(void))block;
    - (__kindof RACStream *)concat:(RACStream *)stream;
    - (__kindof RACStream *)zipWith:(RACStream *)stream;
    

    RACStream还定义了一个Operations的分类,分类中定义并实现了各种信号处理方法,都是使用以上5个方法,直接或间接实现的。子类继承了RACStream之后,便可使用Operations分类中的所有方法。

    RACStream.png
    2、RACSignal

    RACSignal是个核心的信号类,继承并实现了父类RACStream中的5个必要方法。
    empty实现

    //返回一个空信号
    return [[[self alloc] init] setNameWithFormat:@"+empty"];
    

    return实现

    //将传入对象保存,并返回信号
    RACReturnSignal *signal = [[self alloc] init];
    signal->_value = value;
    

    bind实现

    //bind调用了一个传入值,并且返回信号的block
    typedef RACSignal * _Nullable (^RACSignalBindBlock)(ValueType _Nullable value, BOOL *stop);
    //bind内部调用RACSignalBindBlock之后,得到新的信号,然后给新的信号发送sendNext:,并在sendNext:内部给原订阅者发送sendNext:信号,传入包装后的值
    //简化后的bind
    - (RACSignal *)bind:(RACSignalBindBlock (^)(void))block {
        return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
            //拿到实现的block
            RACSignalBindBlock bindingBlock = block();
            return [self subscribeNext:^(id x) {
                BOOL stop = NO;
                //调用数据处理的block
                [bindingBlock(x, &stop) subscribeNext:^(id x) {
                    //并且把数据传递给原订阅者
                    [subscriber sendNext:x];
                }];
            }];
        }] setNameWithFormat:@"[%@] -bind:", self.name];
    }
    
    //调用
    [[self.textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{ return ^RACSignal*(id value, BOOL *stop){
        //bind实现的block内部,拿到数据,包装成信号返回出去
        return [RACSignal return:[NSString stringWithFormat:@"hello: %@",value]];
        };
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"bind : %@",x); // hello: "x"
    }];
    

    concat实现

    //concat简化后
    - (RACSignal *)concat:(RACSignal *)signal {
        return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
            //先给信号本身发送sendNext:
            return [self subscribeNext:^(id x) {
                [subscriber sendNext:x];
            } error:^(NSError *error) {
                [subscriber sendError:error];
            } completed:^{
                //执行完成之后,再给signal发送订阅的消息
                [signal subscribe:subscriber];
            }];
        }] setNameWithFormat:@"[%@] -concat: %@", self.name, signal];
    }
    
    //调用
    RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"signalA"];
        [subscriber sendCompleted];
        return nil;
    }];
    RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"signalB"];
        [subscriber sendCompleted];
        return nil;
    }];
    // 把signalA拼接到signalB后,signalA发送完成,signalB才会被激活 顺序执行
    [[signalA concat:signalB] subscribeNext:^(id  _Nullable x) {
        //先拿到 signalA 的结果 , 再拿到 signalB 的结果 , 执行两次
        NSLog(@"concat result = %@", x);
    }];
    

    zipWith实现

    //简化后的zipWith
    - (RACSignal *)zipWith:(RACSignal *)signal {
        return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
            
            NSMutableArray *selfValues = [NSMutableArray array];
            NSMutableArray *otherValues = [NSMutableArray array];
            __block NSInteger completedCount = 0;
            
            void (^sendNext)(void) = ^{
                @synchronized (selfValues) {
                    //当两个信号都执行完成时,将返回结果打包成元祖返回给原信号
                    //每次都是取数组的第1个元素,取完之后,数组清空,所以信号的数据都是一一对应的
                    RACTuple *tuple = RACTuplePack(selfValues[0], otherValues[0]);
                    [selfValues removeObjectAtIndex:0];
            [otherValues removeObjectAtIndex:0];
                    [subscriber sendNext:tuple];
                    if (completedCount == 2) {
                        //当前信号完成
                        [subscriber sendCompleted];
                    }
                }
            };
            //订阅执行第一个信号
            [self subscribeNext:^(id x) {
                [selfValues addObject:x ?: RACTupleNil.tupleNil];
                completedCount++;
                sendNext();
            }];
            //订阅执行第二个信号
            [signal subscribeNext:^(id x) {
                [otherValues addObject:x ?: RACTupleNil.tupleNil];
                completedCount++;
                sendNext();
            }];
            
            return [RACDisposable disposableWithBlock:^{}];
        }] setNameWithFormat:@"[%@] -zipWith: %@", self.name, signal];
    }
    
    //调用
    RACSignal *zipSignal = [zipSignalA zipWith:zipSignalB];
        
    [zipSignal subscribeNext:^(id  _Nullable x) {
        // x 是一个元祖
        RACTupleUnpack(NSNumber *a, NSNumber *b) = x;
    }];
    

    这里有一篇对ReactiveObjC 详细的原理说明:
    ReactiveObjC详细原理

    1、关于ReactiveObjC使用简介

    相关文章

      网友评论

        本文标题:2、关于ReactiveObjC原理及流程简介

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