1.信號的使用
RACSignal* signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"message"];
return nil;
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"received:%@", x);
}];
// 控制臺輸出: received:message
2.具體流程如下:
(1)創(chuàng)建信號:創(chuàng)建 signal 信號對象的時候,最終創(chuàng)建的是 RACSignal 的子類 RACDynamicSignal 的對象,并傳入一個名為 didSubscribe,參數(shù)為 subscriber 訂閱者對象,返回值為 RACDisposable 對象的 block回調,保存到 signal 對象中;(此時信號為冷信號)
===== RACDynamicSignal.h =====
@property (nonatomic, copy, readonly) RACDisposable * (^didSubscribe)(id<RACSubscriber> subscriber);
===== RACSignal.m =====
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
===== RACDynamicSignal.m =====
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
(2)訂閱信號:訂閱者訂閱信號的時候,需要調用 signal 對象的 subscribeNext: 方法,此方法會創(chuàng)建一個訂閱者對象 subscriber,并傳入一個名為 nextBlock,參數(shù)為 id 類型, 返回值為 RACDisposable 對象的 block回調,保存到subscriber 對象中;
然后調用 signal 對象的訂閱方法 subscribe: ,參數(shù)為前面的 subscriber 對象,返回值為 RACDisposable 對象,此方法中會調用 signal 對象中保存的 didSubscribe 回調;(訂閱后信號變?yōu)闊嵝盘枺?/p>
===== 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<RACSubscriber>)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)發(fā)送信號:didSubscribe block 實現(xiàn)中會調用 subscriber 的 sendNext: 方法,發(fā)送消息給信號對象,表示訂閱者已經(jīng)訂閱信號,sendNext: 方法會同步取出訂閱者對象中保存的 nextBlock 并執(zhí)行,此時信號訂閱流程結束。
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
流程如下圖:
另外,前面創(chuàng)建訂閱者時,傳入了三個參數(shù),nextBlock,error,completed;創(chuàng)建信號的時候,在網(wǎng)絡請求失敗的回調中,我們要[subscriber sendError:netError],也就是發(fā)送錯誤信息,然后再訂閱錯誤事件,也就是調用 subscriberError: 方法,這樣就完成了錯誤信息的訂閱。
completed 事件比較特殊,它有終止訂閱關系的意味,先大致了解一下RACDispoable對象,我們知道,訂閱關系需要有終止的時候,比如,在tableViewCell的復用的時候,cell會訂閱model類產(chǎn)生一個信號,但是當cell被復用的時候,如果不把之前的訂閱關系取消掉,就會出現(xiàn)同時訂閱了2個model的情況。我們可以發(fā)現(xiàn) subscribeNext、subscribeError、subscribeCompleted 事件返回的都是 RACDisopable 對象,當我們希望終止訂閱的時候,調用[RACDisposable dispose]
就可以了。completed 也是這個原理。