2、關(guān)于ReactiveObjC原理及流程簡介

本文是對ReactiveObjC原理簡介

一、流程分析

ReactiveObjC主要有三個關(guān)鍵類:
1、RACSignal 信號
RACSignal 是各種信號的基類,其中RACDynamicSignal是用的最多的動態(tài)信號

2、RACSubscriber 訂閱者
RACSubscriber是實現(xiàn)了RACSubscriber協(xié)議的訂閱者類,這個協(xié)議定義了4個必須實現(xiàn)的方法

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

RACSubscriber主要保存了三個block,跟三個常見的協(xié)議方法一一對應

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

3、RACDisposable 清潔工
RACDisposable 主要是對資源的釋放處理,其中使用RACDynamicSignal時,會創(chuàng)建一個RACCompoundDisposable管理清潔工對象。其內(nèi)部定義了兩個數(shù)組,一個是_inlineDisposables[2]固定長度2的A fast array,超出2個對象的長度由_disposables數(shù)組管理,_inlineDisposables數(shù)組速度快,兩個數(shù)組都是線程安全的。

4、簡單信號調(diào)用流程

結(jié)合以下代碼分析

//1、創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
    //任何時候,都可以發(fā)送信號,可以異步
    [subscriber sendNext:@"發(fā)送信號"];
    [subscriber sendCompleted];
    return nil;
}];
    
//2、訂閱信號
[signal subscribeNext:^(id  _Nullable x) {
     //收到信號時
     NSLog(@"信號內(nèi)容:%@", x);
}];

調(diào)用流程如下:


流程.png
注意:如果didSubscribe是異步執(zhí)行,則會先返回RACDisposable,然后執(zhí)行sendNext:

二、主要類分析

關(guān)于ReactiveObjC所有class的繼承關(guān)系

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是所有信號類的父類,也是一個抽象類。它定義了五個子類必須實現(xiàn)的方法:

+ (__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的分類,分類中定義并實現(xiàn)了各種信號處理方法,都是使用以上5個方法,直接或間接實現(xiàn)的。子類繼承了RACStream之后,便可使用Operations分類中的所有方法。

RACStream.png
2、RACSignal

RACSignal是個核心的信號類,繼承并實現(xiàn)了父類RACStream中的5個必要方法。
empty實現(xiàn)

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

return實現(xiàn)

//將傳入對象保存,并返回信號
RACReturnSignal *signal = [[self alloc] init];
signal->_value = value;

bind實現(xiàn)

//bind調(diào)用了一個傳入值,并且返回信號的block
typedef RACSignal * _Nullable (^RACSignalBindBlock)(ValueType _Nullable value, BOOL *stop);
//bind內(nèi)部調(diào)用RACSignalBindBlock之后,得到新的信號,然后給新的信號發(fā)送sendNext:,并在sendNext:內(nèi)部給原訂閱者發(fā)送sendNext:信號,傳入包裝后的值
//簡化后的bind
- (RACSignal *)bind:(RACSignalBindBlock (^)(void))block {
    return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
        //拿到實現(xiàn)的block
        RACSignalBindBlock bindingBlock = block();
        return [self subscribeNext:^(id x) {
            BOOL stop = NO;
            //調(diào)用數(shù)據(jù)處理的block
            [bindingBlock(x, &stop) subscribeNext:^(id x) {
                //并且把數(shù)據(jù)傳遞給原訂閱者
                [subscriber sendNext:x];
            }];
        }];
    }] setNameWithFormat:@"[%@] -bind:", self.name];
}

//調(diào)用
[[self.textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{ return ^RACSignal*(id value, BOOL *stop){
    //bind實現(xiàn)的block內(nèi)部,拿到數(shù)據(jù),包裝成信號返回出去
    return [RACSignal return:[NSString stringWithFormat:@"hello: %@",value]];
    };
}] subscribeNext:^(id  _Nullable x) {
    NSLog(@"bind : %@",x); // hello: "x"
}];

concat實現(xiàn)

//concat簡化后
- (RACSignal *)concat:(RACSignal *)signal {
    return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
        //先給信號本身發(fā)送sendNext:
        return [self subscribeNext:^(id x) {
            [subscriber sendNext:x];
        } error:^(NSError *error) {
            [subscriber sendError:error];
        } completed:^{
            //執(zhí)行完成之后,再給signal發(fā)送訂閱的消息
            [signal subscribe:subscriber];
        }];
    }] setNameWithFormat:@"[%@] -concat: %@", self.name, signal];
}

//調(diào)用
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發(fā)送完成,signalB才會被激活 順序執(zhí)行
[[signalA concat:signalB] subscribeNext:^(id  _Nullable x) {
    //先拿到 signalA 的結(jié)果 , 再拿到 signalB 的結(jié)果 , 執(zhí)行兩次
    NSLog(@"concat result = %@", x);
}];

zipWith實現(xiàn)

//簡化后的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) {
                //當兩個信號都執(zhí)行完成時,將返回結(jié)果打包成元祖返回給原信號
                //每次都是取數(shù)組的第1個元素,取完之后,數(shù)組清空,所以信號的數(shù)據(jù)都是一一對應的
                RACTuple *tuple = RACTuplePack(selfValues[0], otherValues[0]);
                [selfValues removeObjectAtIndex:0];
        [otherValues removeObjectAtIndex:0];
                [subscriber sendNext:tuple];
                if (completedCount == 2) {
                    //當前信號完成
                    [subscriber sendCompleted];
                }
            }
        };
        //訂閱執(zhí)行第一個信號
        [self subscribeNext:^(id x) {
            [selfValues addObject:x ?: RACTupleNil.tupleNil];
            completedCount++;
            sendNext();
        }];
        //訂閱執(zhí)行第二個信號
        [signal subscribeNext:^(id x) {
            [otherValues addObject:x ?: RACTupleNil.tupleNil];
            completedCount++;
            sendNext();
        }];
        
        return [RACDisposable disposableWithBlock:^{}];
    }] setNameWithFormat:@"[%@] -zipWith: %@", self.name, signal];
}

//調(diào)用
RACSignal *zipSignal = [zipSignalA zipWith:zipSignalB];
    
[zipSignal subscribeNext:^(id  _Nullable x) {
    // x 是一個元祖
    RACTupleUnpack(NSNumber *a, NSNumber *b) = x;
}];

這里有一篇對ReactiveObjC 詳細的原理說明:
ReactiveObjC詳細原理

1、關(guān)于ReactiveObjC使用簡介

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容