創(chuàng)建信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@1];
[subscriber sendNext:@2];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"signal");
}];
}];
上面是創(chuàng)建信號的代碼,下面看看其內(nèi)部是如何實現(xiàn)的:
//RACSignal的createSignal方法內(nèi)部實現(xiàn)是返回一個子類RACDynamicSignal實例對象
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
// 子類RACDynamicSignal的createSignal方法內(nèi)部實例化一個RACDynamicSignal對象
//且這個對象有一個成員變量didSubscribe接收外面?zhèn)鱽淼膁idSubscribe,留著后面訂閱信號時調(diào)用
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
訂閱信號
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
接下來看看信號訂閱內(nèi)部實現(xiàn):
//signal調(diào)用subscribeNext訂閱信號拒炎,該方法內(nèi)部創(chuàng)建了一個RACSubscriber實例對象
//并用該對象作為參賽調(diào)用subscribe方法
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
//方法內(nèi)部實例化一個RACSubscriber對象,該對象的三個成員變量next、error懦趋、completed分別接收三個參數(shù)
+ (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;
}
- (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:^{
//此處的self.didSubscribe就是信號創(chuàng)建時持有的那個block didSubscribe
//調(diào)用didSubscribe,信號創(chuàng)建時的sendNext:消息被觸發(fā)
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
訂閱后消息被發(fā)送疹味,那消息的接收又是如何實現(xiàn)的呢仅叫?下面看看sendNext:內(nèi)部是如何實現(xiàn)的:
- (void)sendNext:(id)value {
@synchronized (self) {
//這個nextblock就是創(chuàng)建subscriber時傳入的block,
//sendNext內(nèi)部就是調(diào)用這個block佛猛,這樣消息接收被觸發(fā)了
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
總結(jié):信號RACSignal的創(chuàng)建實際是創(chuàng)建了一個子類RACDynamicSignal對象惑芭,該對象持有信號創(chuàng)建傳入的block(didSubscribe,用來發(fā)送消息)继找;信號的訂閱內(nèi)部會創(chuàng)建一個RACSubscriber對象(該對象持有nextBlock,用來接收消息),然后這個subscriber對象作為參數(shù)調(diào)用subscribe方法遂跟;subscribe方法內(nèi)部以subscriber作為參賽調(diào)用信號創(chuàng)建時的didSubscribe。這樣didSubscribe內(nèi)部通過sendNext方法發(fā)送消息婴渡,而sendNext內(nèi)部會調(diào)用nextBlock接收消息幻锁。至此,信號的創(chuàng)建边臼、訂閱哄尔,消息的發(fā)送和接收全部完成。
RACDisposable類封裝了刪除和清理訂閱所需的工作柠并,下面是其內(nèi)部實現(xiàn):
+ (instancetype)disposableWithBlock:(void (^)(void))block {
return [[self alloc] initWithBlock:block];
}
- (instancetype)initWithBlock:(void (^)(void))block {
NSCParameterAssert(block != nil);
self = [super init];
_disposeBlock = (void *)CFBridgingRetain([block copy]);
OSMemoryBarrier();
return self;
}
創(chuàng)建RACDisposable時會傳入一個block岭接,我們可以用它做一些訂閱結(jié)束后的處理富拗;當(dāng)訂閱者銷毀或者取消訂閱時這個block會觸發(fā)調(diào)用;
// 取消訂閱
- (void)dispose {
void (^disposeBlock)(void) = NULL;
while (YES) {
void *blockPtr = _disposeBlock;
if (OSAtomicCompareAndSwapPtrBarrier(blockPtr, NULL, &_disposeBlock)) {
if (blockPtr != (__bridge void *)self) {
disposeBlock = CFBridgingRelease(blockPtr);
}
break;
}
}
if (disposeBlock != nil) disposeBlock();
}
由dispose內(nèi)部實現(xiàn)可以看出取消訂閱時鸣戴,只要不為空一定會調(diào)用創(chuàng)建時傳入的block啃沪;