您的位置:首页 > 其它

RAC冷信号

2016-10-13 11:29 260 查看

概念

首先,信号使用发布订阅模式。

冷信号:订阅者订阅了信号,它才会发布,并且立即把信号中的所有操作发布。

热信号:信号发布与订阅者订阅与否无关,订阅者可以在信号的发布过程中订阅。

例子分析

冷信号

冷信号像调用函数一样,订阅就是去调用。看下面的代码:

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendNext:@2];
[subscriber sendNext:@3];
[subscriber sendCompleted];
return nil;
}];
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 1 receive: %@", x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 2 receive: %@", x);
}];


输出如下:

Subscriber 1 receive: 1
Subscriber 1 receive: 2
Subscriber 1 receive: 3
Subscriber 2 receive: 1
Subscriber 2 receive: 2
Subscriber 2 receive: 3


可以看到,我们创建了一个发布信号(发布者),它做了什么事情呢?它就是对其订阅者发送了三次数字。

谁是订阅者呢,signal的subscribeNext即为订阅者,在下面的程序分析中可以看到subscribeNext方法内部创建了subscriber对象。

RAC是函数式编程,所以发布者的操作和订阅者的操作都以block参数的形式分别传入。

OK,看程序的输出可以看出,就像之前提到的那样,订阅了信号后,发布者会立即执行发布,像调了函数一样。那么内部是怎样做的呢?

一步步来看,先看创建发布信号:

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}


可以看出createSignal的信号类型是RACDynamicSignal,那么它的createSignal:是怎么初始化的呢?

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}


可以看到只是初始化了signal对象,而signal的_didSubscribe成员保存下了发布block。

下面看发布信号的发布内容:

在程序可以看到subscriber sendNext,subscriber是符合RACSubscriber协议的对象,那么就可能有很多种的订阅者,这个发布block做的就是调用每个订阅者sendNext。

这里我们先知道了这个订阅者类型是RACPassthroughSubscriber

//RACPassthroughSubscriber中
- (void)sendNext:(id)value {
if (self.disposable.disposed) return;

if (RACSIGNAL_NEXT_ENABLED()) {
RACSIGNAL_NEXT(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description), cleanedDTraceString([value description]));
}

[self.innerSubscriber sendNext:value];
}


innerSubscriber其实就是封装后又起了个名子的订阅者,也就是下面的真正订阅者。这里innerSubscriber sendNext:如下

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

nextBlock(value);
}
}


真正的sendNext只做了简单的事,就是执行nextBlock(value),nextBlock是谁呢?可以猜到,下面的RACSubscriber要subscribeNext,是的,这个nextBlock就是subscribeNext的block。

最后来看订阅者:

- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);

RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}


可以看到,订阅block先生成订阅者RACSubscriber,然后把nextBlock等各订阅block保存下来。

然后[self subscribe:o],self是信号,o是RACSubscriber,

在RACDynamicSignal中查看subscribe:方法

- (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
4000
addDisposable:innerDisposable];
}];

[disposable addDisposable:schedulingDisposable];
}

return disposable;
}


OK,我们看到了RACPassthroughSubscriber,就是上面发布信号发布操作里的subscriber,对真正订阅者重新封装了一下。

接下来的self.didSubscribe(subscriber);是真正执行信号发布操作block的地方,回顾一下,是上面的signal->_didSubscribe = [didSubscribe copy]; 命名上已经告诉我们了,didSubscribe,订阅完毕,该发布了。

其中RACDisposable是释放相关的,我们以后再讲。

总结

好了,跟着这几行代码走了下来,是不是有点糊涂了,那就总结一下流程,并调整一下上面的顺序。

信号的订阅—发布

创建发布者信号RACSignal(其实是RACDynamicSignal)

发布block传入,保存命名为didSubscribe

订阅block传入,subscribeNext:方法内部生成subscriber对象,并与订阅block封装成RACPassthroughSubscriber

subscribeNext:方法内,由信号调用subscibe:方法来使得订阅者订阅信号。

subscibe:方法内调用发布block didSubscribe来立即执行发布操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  RAC 信号 冷信号