RAC(ReactiveCocoa)介绍(四)——流程分析

2019-04-02 14:59:26 浏览数 (1)

之前的文章一直在写关于RAC框架中某些方法的实现原理、具体使用作用以及代码实现,基本上也对RAC有了一个初步的认识。这次不打算继续记录关于RAC中具体的方法,准备放到后面慢慢分析,这篇准备继续深入探究一下RAC中信号的流程分析。这样对RAC认识会更加深刻,有助于后续的理解。 首先,贴上之前的代码为例

代码语言:javascript复制
    //1. 创建signal信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        //subscriber并不是一个对象
        //3. 发送信号
        [subscriber sendNext:@"send one Message"];
        
        //发送error信号
        NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:1001 userInfo:@{@"errorMsg":@"this is a error message"}];
        [subscriber sendError:error];
        
        //4. 销毁信号
        return [RACDisposable disposableWithBlock:^{
            NSLog(@"signal已销毁");
        }];
    }];
    
    //2.1 订阅信号
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    //2.2 针对实际中可能出现的逻辑错误,RAC提供了订阅error信号
    [signal subscribeError:^(NSError * _Nullable error) {
        NSLog(@"%@",error);
    }];

执行打印结果

按照代码中的执行步骤: 在创建信号signal之后,订阅了两个信号signal;当分别发送两个信号signal时,订阅信号signal方法block中首先打印出发送信号signal的内容,然后执行信号signal销毁。注意:RAC方法中的block代码块,

  1. 创建信号signal 在创建信号signal的方法createSignal中,可以看到是由RACDynamicSignal类创建的信号signal

创建信号方法 方法中可以看出,将block代码块didSubscribe复制copy给了当前的实例变量_didSubscribe

  1. 订阅信号signal 订阅信号方法subscribeNext中,使用RACSubscriber类进行了初始化并将next的block保存。在该实例化方法中,也可将error的block与completed的block传入,此处因外部使用subscribeNext方法,所以只传入next。与之相对应的,subscribeError方法则是初始化并保存了error的block,subscribeCompleted方法是初始化并保存了completed的block。

将订阅信号进行初始化 订阅信号实现代码中,[self subscribe:o]方法中的self的类是RACDynamicSignal(刚才第1步中创建信号类为RACDynamicSignal),进入RACDynamicSignal类中的subscribe方法。

RACDynamicSignal类中subscribe实现方法

RACCompoundDisposable为组合式销毁栈,用于处理信号的销毁。至于其中如何运作的,之后专门用一篇幅来详细介绍。

subscriber被重新指向由RACPassthroughSubscriber类初始化的对象,通过该类创建的对象才是信号真正的订阅者。通过该方法将信号、订阅者、销毁者全部传入进去,换句话说,就是该方法将信号、订阅者、销毁者进行了关联,从而实现不断订阅、不断销毁。此处亦是RAC的核心之一。

代码语言:javascript复制
            RACDisposable *innerDisposable = self.didSubscribe(subscriber);
            [disposable addDisposable:innerDisposable];

此处代码要注意到,是执行了self.didSubscribe(id<RACSubscriber> subscriber)代码块。而self.didSubscribe(id<RACSubscriber> subscriber)是在创建信号的时候,进行了copy赋值操作,在订阅者这里进行执行操作。所以,在第2步订阅信号创建的时候,会进入第1步创建信号的block代码块中寻找并执行自定义添加的代码,也就是准备开始执行第一张代码图中的第3步、第4步操作。

第3步,发送信号signal 通过进入RACSubscriber类中的sendNext方法查看实现代码

sendNext方法实现

保证RACSubscriber类的线程安全,将self.next代码块copy至一个本地代码块,并将其执行。此处的self.next正是在第2步订阅信号过程中,保存的nextBlock代码块。 最终在执行发送信号signal的时候,会查找并执行在第2步订阅信号方法中的block代码块。

因此,整个信号流程的执行,也正是函数式编程思想的完美体现。

最后再配上一张流程图,来总结一下上述实现的步骤。

RAC流程分析简图

0 人点赞