我在之前一篇文章说到过冷信号带来的问题, 有时候通过将其转为热信号就可以避免, 这篇文章将会介绍如何将一个冷信号转为热信号。
方式1: subscribe
直接上代码吧
|
首先RACSubject 是遵守 RACSubscriber
协议的,所以我们可以将 subject 当作 subscriber 传入subscribe方法中。subscripe 的实现如下
|
可以看到 self.didSubscribe(subscriber);
这里 调用了signal 的 didSubscribe 这个block ,并且将 subscriber(也就是subject) 作为参数传入。 看过上篇文章你就会知道,第一段代码中block会被执行,也就是 [subscriber sendNext:@"signal"];
也会被执行,这里的subscriber其实还是我们创建的subject,这样的话,第一段代码其实可以简化为
|
不过平时我们不会这么去使用,RACSignal+Operationsn 这个类别中提供了更多优良姿势,下面一一介绍。
方式2: multicast
用法如下:
|
首先我们看一下 muticast 的实现
|
其实就是生成了一个 RACMulticastConnection 实例,并将 signal(sourceSignal) 和 subject(signal) 分别保存起来。
所以,下面对 connection.signal 的订阅 就是对subject的订阅。
接下来再来看一下 connect 的实现
|
可以看到 [self.sourceSignal subscribe:_signal];
这里其实就是 [signal subscripe:subject]
不再多说。
这里有必要说一下 OSAtomicCompareAndSwap32Barrier
原型如下
|
如果 __theValue
的值是 __oldValue
该方法会将 __theValue
由 __oldValue
换为 __newValue
并且返回YES,而如果 __theValue
的值已经是 __newValue
,则不做交换并且返回NO。因此 connect 方法中 subscribe 方法只会被执行一次。
除了connect之外,RACMulticastConnection 类中还提供了一个autoconnect方法,实现如下
|
他会返回一个RACDynamicSignal ,但这个信号被订阅时执行connect方法,因此使用autoconnect的姿势如下:
|
RACMulticastConnection 用于将一个信号的订阅分享给多个订阅者,你需要使用
[RACSignal publish]
或者[RACSignal multicast:]
来实例RACMulticastConnection对象,并且使用connect
或autoconnect
来执行订阅
方式3: publish
在 RACSignal+Operations 这个类别中提供了publish方法来生成RACMulticastConnection示例,实现如下:
|
该方法只是对 multicast 方法的一个简单封装(在内部创建一个subject并对其multicast),使用 publish 更为方便快捷。使用如下:
|
在 RACSignal+Operations 中除了 multicast 与 publish 方法外,还提供了 replay 、replayLast、replayLazily 这三个方法。其实他们都是对 multicast 方法的封装
方式4: replay
实现如下
|
publish中操作的是RACSubject并且没有执行connect方法然后返回的是connection实例,而replay是对RACReplaySubject的操作,并且执行了connect方法,返回值是RACReplaySubject的实例。那么我们接受到replay的返回值其实就是拿到了由冷信号转换得到的RACReplaySubject,由于执行过connect方法,所以这个热信号已经进行过sendnext,后续只需要对其订阅即可触发。使用如下:
|
方式5: replayLast
|
可以看到 replayLast 的实现与replay想比只是在对RACReplaySubject的初始化方法,这里将RACReplaySubject中valuesReceived数组的capacity设为1, 所以当这个RACReplaySubject被订阅时只会执行“在他之前的的最后一个” sendNext。 replayLast 顾名思义只会重复订阅之前最后的一条sendNext。
方式6: replayLazily
|
和replay不同的是这里将 connect 操作 套在了 defer 方法里面(defer将RACReplaySubject用RACDynamicSignal包裹起来)。
我们来看defer的实现
|
只有 defer 方法返回的信号被订阅之后才会执行 return [block() subscribe:subscriber];
,
将 return [block() subscribe:subscriber];
展开就是
|
因此 replayLazily 返回的信号只有在被订阅的时候才会执行 [connection.signal subscripe:subscriber]
, replayLazily 叫做 replayLazily 再合适不过。
replayLazily 的使用如下:
|
总结
- 通过冷信号subscribe一个热信号即可通过将热信号当作subscriber(订阅者)来进行sendNext等操作,也就是将冷信号转为了热信号;
- multicast就是基于上述原理来实现的;
- publish replay replayLast replayLazily 都是基于 multicast 的封装,满足上的不同使用场景。