美文网首页
ReactiveObjC源码分析

ReactiveObjC源码分析

作者: 林君毅小号_001 | 来源:发表于2022-05-12 22:31 被阅读0次

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

    RACSignal
    信号基类RACSignal(继承自RACStream),调用createSignal:(RACDisposable * (^)(id<RACSubscriber> 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<RACSubscriber>  _Nonnull subscriber) {
            if (iii % 2== 0) {
                [subscriber sendNext:input];
                [subscriber sendCompleted];
            } else {
                [subscriber sendError:nil];
            }
            iii++;
            return nil;
        }];
    }];
    
    [button.rac_command.executionSignals subscribeNext:^(RACSignal<id> * _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源码分析

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