RAC冷信号

概念

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

冷信号:订阅者订阅了信号,它才会发布,并且立即把信号中的所有操作发布。
热信号:信号发布与订阅者订阅与否无关,订阅者可以在信号的发布过程中订阅。

例子分析

  • 冷信号
    冷信号像调用函数一样,订阅就是去调用。看下面的代码:
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 addDisposable:innerDisposable];
        }];

        [disposable addDisposable:schedulingDisposable];
    }

    return disposable;
}

OK,我们看到了RACPassthroughSubscriber,就是上面发布信号发布操作里的subscriber,对真正订阅者重新封装了一下。
接下来的self.didSubscribe(subscriber);是真正执行信号发布操作block的地方,回顾一下,是上面的signal->_didSubscribe = [didSubscribe copy]; 命名上已经告诉我们了,didSubscribe,订阅完毕,该发布了。
其中RACDisposable是释放相关的,我们以后再讲。

总结

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

信号的订阅—发布

  1. 创建发布者信号RACSignal(其实是RACDynamicSignal)
  2. 发布block传入,保存命名为didSubscribe
  3. 订阅block传入,subscribeNext:方法内部生成subscriber对象,并与订阅block封装成RACPassthroughSubscriber
  4. subscribeNext:方法内,由信号调用subscibe:方法来使得订阅者订阅信号。
  5. subscibe:方法内调用发布block didSubscribe来立即执行发布操作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值