iOS 进阶ios基础

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

2018-01-16  本文已影响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使用简介

上一篇下一篇

猜你喜欢

热点阅读