ReactiveObjC源码分析

基于信号的响应式编程框架。

RACSignal
信号基类RACSignal(继承自RACStream),调用createSignal:(RACDisposable * (^)(id subscriber))didSubscribe方法会生成冷信号,并保存didSubscribe(此时并不会执行didSubscribe)。
冷信号只有被订阅时,才会变成热信号。通过调用RACSignal的subscribeNext:方法,会生成一个RACSubscriber订阅者, 之后调用subscribe: 方法(实际是调用RACDynamicSignal的subscribe:方法),在subscribe: 内部会调用didSubscribe。
常用的信号:RACDynamicSignal事件流信号、RACErrorSignal错误信号、RACEmptySignal空信号(不触发订阅事件)。

RACSubscriber
订阅者,sendNext触发subcribeNext,sendCompleted触发subscribeCompleted,sendError触发subscribeError。sendNext后如果要移除信号,防止资源占用导致事件流堵塞,需调用sendCompleted。
用流水线的角度来看,RACSignal相当于管线,RACSubscriber相当于工人,工人对传过来的信号进行加工处理,触发各种事件。
流程: createSianal,生成信号同时保存didSubscribe—>subscribeNext生成订阅者,并调用—>subscribe—>didSubscribe—>合适时机调用sendNext等方法—>触发subscribeNext等block执行块。

RACSubject
继承自RACSignal,热信号。RACSubject不止有一个订阅者,其内部维护一个订阅者数组。同时其能自发调用sendNext方法。
流程:sendNext—>subscibeNext

RACCommand
比较上层的工人,内部维护了多个RACSubject。
executionSignals 执行内部事务调用sendNext、sendError的响应信号。
errors 执行内部事务调用sendError的响应信号。
等等。
以UIButton+RACCommandSupport的流程为例:
RACCommand的initWithSignalBlock生成一个rac_command,并保存signalBlock,把rac_command传给button。
button点击—>rac_command.execute—>调用signalBlock生成信号—>signalBlock内部的didSubscribe—>subscribe.sendNext、sendError—>触发executionSignals.subscribeNext、errors.subscribeNext。

static NSInteger iii = 0;
button.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
    NSLog(@"button pressed");
    return [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        if (iii % 2== 0) {
            [subscriber sendNext:input];
            [subscriber sendCompleted];
        } else {
            [subscriber sendError:nil];
        }
        iii++;
        return nil;
    }];
}];

[button.rac_command.executionSignals subscribeNext:^(RACSignal * _Nullable x) {
    RACSignal *s = (RACSignal *)x;
    [s subscribeNext:^(id  _Nullable x) {
        NSLog(@"执行事件");
    }];
}];

[button.rac_command.errors subscribeNext:^(NSError * _Nullable x) {
    NSLog(@"错误发生");
}];

bind
map、flattenMap等方法都是基于bind,而bind的实现过程也能充分体现ReactiveObjC基于信号通信的思想。
信号1调用bind:bindBlcok❶,会返回信号2,信号2的didSubscribe❷调用self的subscribeNext:error:completed方法(即信号1的subscribeNext:error:completed❸),在subscribeNext中用bindBlock生成信号3❹,并调用信号3的subscribeNext❺,subscribeNext的执行块会调用信号2的subscriber.sendNext❻, 从而触发信号2的subscribeNext执行块❼。
这样每次信号1触发时,就会触发信号2,从而实现了新信号绑定旧信号的功能。
流程:信号1的订阅者subscriber1.sendNext—>信号1的subscribeNext block(❸处)—>生成信号3—>信号3的subscribeNext block(❺处)—>信号2的subscriber.sendNext(❻处)—>信号2的subscribeNext block。
从而实现了信号1触发时,信号2的subscribeNext block能被执行。

常用的宏
RAC(id, property)
RACObserve(id, property)等

参考源码:https://github.com/ReactiveCocoa/ReactiveObjC

你可能感兴趣的:(ReactiveObjC源码分析)