RACSignal信号订阅流程的简单理解

1.信号的使用

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

     [subscriber sendNext:@"message"];
     return nil;
}];

[signal subscribeNext:^(id _Nullable x) {

     NSLog(@"received:%@", x);
}];

// 控制台输出: received:message

2.具体流程如下:

(1)创建信号:创建 signal 信号对象的时候,最终创建的是 RACSignal 的子类 RACDynamicSignal 的对象,并传入一个名为 didSubscribe,参数为 subscriber 订阅者对象,返回值为 RACDisposable 对象的 block回调,保存到 signal 对象中;(此时信号为冷信号)

===== RACDynamicSignal.h =====
@property (nonatomic, copy, readonly) RACDisposable * (^didSubscribe)(id subscriber);

===== RACSignal.m =====
+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe {

      return [RACDynamicSignal createSignal:didSubscribe];
}

===== RACDynamicSignal.m =====

+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe {

     RACDynamicSignal *signal = [[self alloc] init];
     signal->_didSubscribe = [didSubscribe copy];

     return [signal setNameWithFormat:@"+createSignal:"];
}

(2)订阅信号:订阅者订阅信号的时候,需要调用 signal 对象的 subscribeNext: 方法,此方法会创建一个订阅者对象 subscriber,并传入一个名为 nextBlock,参数为 id 类型, 返回值为 RACDisposable 对象的 block回调,保存到subscriber 对象中;
然后调用 signal 对象的订阅方法 subscribe: ,参数为前面的 subscriber 对象,返回值为 RACDisposable 对象,此方法中会调用 signal 对象中保存的 didSubscribe 回调;(订阅后信号变为热信号)

===== RACSubscriber.m =====
@property (nonatomic, copy) void (^next)(id value);

===== RACSignal.m =====
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {

     NSCParameterAssert(nextBlock != NULL);
     RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];

     return [self subscribe:o];
}

===== RACDynamicSignal.m =====

- (RACDisposable *)subscribe:(id)subscriber {

     NSCParameterAssert(subscriber != nil);
     RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];

     subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
     if (self.didSubscribe != NULL) {

         RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
             RACDisposable *innerDisposable = self.didSubscribe(subscriber);
             [disposable addDisposable:innerDisposable];
         }];
         [disposable addDisposable:schedulingDisposable];
     }
     return disposable;
}

(3)发送信号:didSubscribe block 实现中会调用 subscriber 的 sendNext: 方法,发送消息给信号对象,表示订阅者已经订阅信号,sendNext: 方法会同步取出订阅者对象中保存的 nextBlock 并执行,此时信号订阅流程结束。

- (void)sendNext:(id)value {

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

流程如下图:

RACSignal.png

另外,前面创建订阅者时,传入了三个参数,nextBlock,error,completed;创建信号的时候,在网络请求失败的回调中,我们要[subscriber sendError:netError],也就是发送错误信息,然后再订阅错误事件,也就是调用 subscriberError: 方法,这样就完成了错误信息的订阅。

completed 事件比较特殊,它有终止订阅关系的意味,先大致了解一下RACDispoable对象,我们知道,订阅关系需要有终止的时候,比如,在tableViewCell的复用的时候,cell会订阅model类产生一个信号,但是当cell被复用的时候,如果不把之前的订阅关系取消掉,就会出现同时订阅了2个model的情况。我们可以发现 subscribeNext、subscribeError、subscribeCompleted 事件返回的都是 RACDisopable 对象,当我们希望终止订阅的时候,调用[RACDisposable dispose]就可以了。completed 也是这个原理。

你可能感兴趣的:(RACSignal信号订阅流程的简单理解)