RAC 之 RACSignal 使用与源码分析

RACSignal 使用

   // 1 创建信号
    @weakify(self)
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {

        @strongify(self)
        self.subsrcribe = subscriber;

        // 3 发送信号
        [subscriber sendNext:@"hahah"];

        return [RACDisposable disposableWithBlock:^{
            NSLog(@"销毁了");
        }];
    }];

    // 2 订阅信号
    [signal subscribeNext:^(id  _Nullable x) {
        // 第 3 步 发送信号后, 此处 block 会被回调
        NSLog(@"subscribeNext:%@",x);
    }];

根据上述代码流程,RACSignal 的使用分别有 3 步

  • 创建:实例一个 RACSignal对象,并实现一个能够获取 subscriber 订阅者的 block
  • 订阅:使用RACSignal对象进行订阅,用于获取发送信号后的回调结果
  • 发送信号:使用subscriber 订阅者在特定位置发送信号(发送结果),订阅信号的 block 获取结果

一、RACSignal 的创建

以下我们开始分析一下 RACSignal类型的对象是怎么来的

    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {

        return [RACDisposable disposableWithBlock:^{
            
        }];
    }];

上述RACSignal 的创建 方法,

//  RACSignal.h
+ (RACSignal<ValueType> *)createSignal:
(RACDisposable * _Nullable (^)(id<RACSubscriber> subscriber))didSubscribe
//  RACSignal.m
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
     //RACDynamicSignal 继承于 RACSignal
    return [RACDynamicSignal createSignal:didSubscribe];
}

因为返回的是 RACSignal类型,却使用了

return [RACDynamicSignal createSignal:didSubscribe];

由此可得 RACDynamicSignal 这个子类做了一系列的实例化和包装处理,如下:

//RACDynamicSignal.m

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    RACDynamicSignal *signal = [[self alloc] init];
    signal->_didSubscribe = [didSubscribe copy];
        //  setNameWithFormat: 进行了一些列的底层打印日志操作,
       //   最后还是返回了一个 RACSignal 的对象
    return [signal setNameWithFormat:@"+createSignal:"];
}

二、RACSignal 订阅信号

    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"subscribeNext:%@",x);
    }];

上述方法是在 RACSignal (Subscription)类别里的一个方法:

- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
    NSCParameterAssert(nextBlock != NULL);
    
    // 创建 subscribe 对象 并保存 Next、Error、Completed 三个Block
    RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    // 传入 subscribe 并创建 disposable
    return [self subscribe:o];
}

RACSubscriber的对象主要保存了 Next、Error、Completed 3个Block,再往里面跟一层如下:

// RACSubscriber.m
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
    RACSubscriber *subscriber = [[self alloc] init];

    subscriber->_next = [next copy];
    subscriber->_error = [error copy];
    subscriber->_completed = [completed copy];

    return subscriber;
}

然后回到 上面的类别: RACSignal (Subscription)

  return [self subscribe:o];

上述方法虽然是在本类别里调用

- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    NSCAssert(NO, @"This method must be overridden by subclasses");
    return nil;
}

但却被子类 RACDynamicSignal 重写了

// RACDynamicSignal.m
#pragma mark Managing Subscribers
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    NSCParameterAssert(subscriber != nil);

    // 传入 subscribe 并创建 disposable,
    // 复合销毁者
    RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
    
    /**
     *  subscriber --- RACSubscriber
     *  signal     --- self 
     *  disposable
     */

    //  新的(RACPassthroughSubscriber*)subscriber 拥有:disposable、signal、subscribe 三者合成
    subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];

    // signal 有执行 didsubscribe Block 往下走
    if (self.didSubscribe != NULL) {
        
        //  这里需要注意!!!!  如果开启了异步操作,RACScheduler.subscriptionScheduler 的类型是 “RACTargetQueueScheduler” 并在子线程执行 【RACTargetQueueScheduler schedule:】
        
        RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
            // 这一步 self.didSubscribe(subscriber) 进行block 回调出去
            RACDisposable *innerDisposable = self.didSubscribe(subscriber);
            // 添加销毁
            [disposable addDisposable:innerDisposable];
        }];

        [disposable addDisposable:schedulingDisposable];
    }
    
    return disposable;
}

上述代码我们主要看订阅者subscriber 的回调流程:

// 只要外部执行了
[RACSignal  createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
  // 这里得到 subscriber 的底层回调
}

 当底层使用 self.didSubscribe(subscribe) 就会回调出去上面的代码块里

小结一下整个订阅过程主要做了的就是:
signal 订阅了 subscribeNext:^(id _Nullable x) 的 block,并内部配置了 subscribe,即:

    subscriber->_next = [next copy];
    subscriber->_error = [error copy];
    subscriber->_completed = [completed copy];

此时 subscriber拥有了下面 signal的block 实现

// 三种订阅原理都是一样
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"subscribeNext:%@",x);
     }];

    [signal subscribeError:^(NSError * _Nullable error) {
        NSLog(@"subscribeError");
    }];

    [signal subscribeCompleted:^{
        NSLog(@"subscribeCompleted");
    }];

下一步subscriber 就可以根据不同场景发送信号进行 block 回调了

三、 RACSignal 发送信号

使用subscriber发送信号:

        [subscriber sendNext:@"hahah"];
    
        [subscriber sendError:nil];

        [subscriber sendCompleted];
// RACSubscriber.m
#pragma mark RACSubscriber

- (void)sendNext:(id)value {
    @synchronized (self) {
        void (^nextBlock)(id) = [self.next copy];
        if (nextBlock == nil) return;
        nextBlock(value);
    }
}

- (void)sendError:(NSError *)e {
    @synchronized (self) {
        void (^errorBlock)(NSError *) = [self.error copy];
        // 在回调 block 之前 ,执行了销毁方法
        [self.disposable dispose];

        if (errorBlock == nil) return;
        errorBlock(e);
    }
}

- (void)sendCompleted {
    @synchronized (self) {
        void (^completedBlock)(void) = [self.completed copy];
        // 在回调 block 之前 ,执行了销毁方法
        [self.disposable dispose];

        if (completedBlock == nil) return;
        completedBlock();
    }
}

上面 subscriber 根据不同方法分别调用了 nextBlock(value),errorBlock(e),completedBlock() 使得第二步 signal的订阅信号得到了回调结果;

值得注意的是:

- (void)sendError:(NSError *)e
- (void)sendCompleted;

这两个方法的实现里,分别都调用了

[self.disposable dispose];

这部操作把 subscriber进行了销毁, 之后的subscriber如果再调用 sendNext, sendError , sendCompleted 或其他发送信号的方法,都已经失效了。

关于 RACSignal,RACSubscriber 就暂时介绍到这里,上述涉及到RACDisposable,RACScheduler 没有作出过多的解释,后续抽时间会继续写下去。

以上内容纯粹个人见解,仅用于分享交流;如有描述不当之处,欢迎指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。