ObjectiveCBridging
RACSignal -> Signal, SignalProducer
RACCommand -> Action
RACScheduler -> SchedulerType
RACDisposable -> Disposable
具体可以参看ObjectiveCBridging.swift
RAC4的 Signal 对应RAC2的 RACSubject,为热信号,SignalProducer 对应 RACSignal 为冷信号。
热信号是主动的,就算没有订阅者也会即刻推送;冷信号是被动的,有订阅者才推送
热信号可以有多个订阅者,一对多;冷信号只能一对一,当有新的订阅者,信号是重新完整发送的
形象的说:热信号像是直播,冷信号像是点播
热信号
参看一个例子
// 创建信号
let (signal, observer) = Signal<String, NSError>.pipe()
// 监听器1:立即监听
signal.observeResult {
NSLog("Subscriber 1 get a next value: \($0)")
}
// 监听器2:0.1s后监听
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 0.1)) {
signal.observeResult({ (result) in
NSLog("Subscriber 2 get a next value: \(result)")
})
}
// 发送Next信号:1s后发送"package 1"
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
NSLog("Signal send package 1 ...")
observer.sendNext("package 1")
}
// 监听器3:1.1s后监听
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1.1)) {
signal.observeResult {
NSLog("Subscriber 3 get a next value: \($0)")
}
}
// 发送Next信号: 2s后发送"package 2"
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 2)) {
NSLog("signal send package 2 ...")
observer.sendNext("package 2")
}
运行:
2016-12-18 19:42:16.206588 TestRAC4[695:389286] start ...
2016-12-18 19:42:17.249072 TestRAC4[695:389286] Signal send package 1 ...
2016-12-18 19:42:17.254583 TestRAC4[695:389286] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 19:42:17.254899 TestRAC4[695:389286] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 19:42:18.393983 TestRAC4[695:389286] signal send package 2 ...
2016-12-18 19:42:18.394386 TestRAC4[695:389286] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 19:42:18.394582 TestRAC4[695:389286] Subscriber 2 get a next value: .Success(package 2)
2016-12-18 19:42:18.394769 TestRAC4[695:389286] Subscriber 3 get a next value: .Success(package 2)
正如之前提到的热信号的特点,热信号不关心是否有人监听,有产生信号就发送,有人监听就发个监听者。0.1s,2s分别发送next事件,0s,0.1s,1.1s分别产生一个监听者,所以第一个信号只有监听者1,2能收到;第二个next发出时三个监听器都准备好了,都能收到。
冷信号
再看看冷信号的例子:
let producer = SignalProducer<String, NSError>.init { (observer, _) in
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
NSLog("Producer send package 1 ...")
observer.sendNext("package 1")
}
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 2)) {
NSLog("Producer send package 2 ...")
observer.sendNext("package 2")
}
}
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 2)) {
NSLog("setup Subsrciber 1")
producer.startWithResult({ (msg) in
NSLog("Subscriber 1 get a next value: \(msg)")
})
}
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 3)) {
NSLog("setup Subsrciber 2")
producer.startWithResult({ (msg) in
NSLog("Subscriber 2 get a next value: \(msg)")
})
}
以下是输出:
2016-12-18 20:05:36.396118 TestRAC4[703:394073] start ...
2016-12-18 20:05:38.600637 TestRAC4[703:394073] setup Subsrciber 1
2016-12-18 20:05:39.681697 TestRAC4[703:394073] setup Subsrciber 2
2016-12-18 20:05:39.682077 TestRAC4[703:394073] Producer send package 1 ...
2016-12-18 20:05:39.685559 TestRAC4[703:394073] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 20:05:40.753463 TestRAC4[703:394073] Producer send package 2 ...
2016-12-18 20:05:40.753865 TestRAC4[703:394073] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 20:05:40.754679 TestRAC4[703:394073] Producer send package 1 ...
2016-12-18 20:05:40.754898 TestRAC4[703:394073] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 20:05:41.881230 TestRAC4[703:394073] Producer send package 2 ...
2016-12-18 20:05:41.881673 TestRAC4[703:394073] Subscriber 2 get a next value: .Success(package 2)
使用冷信号,信号在程序起来第1s,2s分别发送了一个next。而在2s,3s分别建立了一个监听。第一个监听建立后1s,2s分别收到一个信号。第二信号建立的1s,2s后也分别收到了同样的信号。
冷信号转化为特殊热信号
由于冷信号每次订阅都重新发送事件,故有时候我们需要多次订阅时会造成不希望的重复发送(这称为信号的副作用),我们需要将冷信号转为具有热信号特征的冷信号。
参看一个例子,我们用冷,热信号在0.1s后发送三个next事件,然后如下进行监听:
// 我们用2个监控来监控generateSignal()产生的信号
let signal = generateSignal()
signal.startWithResult{ NSLog("Subscriber 1 get a next value: \($0)") }
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
signal.startWithResult{ NSLog("Subscriber 2 get a next value: \($0)") }
}
先看看如果是产生了普通的冷信号:
func generateSignal() -> SignalProducer<String, NSError> {
let producer = SignalProducer<String, NSError>.init { (observer, _) in
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
NSLog("producer send package 1 ...")
observer.sendNext("package 1")
NSLog("producer send package 2 ...")
observer.sendNext("package 2")
NSLog("producer send package 3 ...")
observer.sendNext("package 3")
}
}
return producer
}
输出如我们所料,信号被重复发送了。
2016-12-18 21:46:21.295670 TestRAC4[742:413995] start ...
2016-12-18 21:46:22.389634 TestRAC4[742:413995] producer send package 1 ...
2016-12-18 21:46:22.397032 TestRAC4[742:413995] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 21:46:22.397397 TestRAC4[742:413995] producer send package 2 ...
2016-12-18 21:46:22.398235 TestRAC4[742:413995] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 21:46:22.398415 TestRAC4[742:413995] producer send package 3 ...
2016-12-18 21:46:22.398608 TestRAC4[742:413995] Subscriber 1 get a next value: .Success(package 3)
2016-12-18 21:46:23.496484 TestRAC4[742:413995] producer send package 1 ...
2016-12-18 21:46:23.496886 TestRAC4[742:413995] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 21:46:23.497061 TestRAC4[742:413995] producer send package 2 ...
2016-12-18 21:46:23.497255 TestRAC4[742:413995] Subscriber 2 get a next value: .Success(package 2)
2016-12-18 21:46:23.497413 TestRAC4[742:413995] producer send package 3 ...
2016-12-18 21:46:23.498869 TestRAC4[742:413995] Subscriber 2 get a next value: .Success(package 3)
如果改成热信号呢?
func generateSignal() -> Signal<String, NSError> {
let (signal, observer) = Signal<String, NSError>.pipe()
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 0.1)) {
NSLog("producer send package 1 ...")
observer.sendNext("package 1")
NSLog("producer send package 2 ...")
observer.sendNext("package 2")
NSLog("producer send package 3 ...")
observer.sendNext("package 3")
}
return signal
}
let signal = generateSignal()
signal.observeResult { NSLog("Subscriber 1 get a next value: \($0)") }
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
signal.observeResult{ NSLog("Subscriber 2 get a next value: \($0)") }
}
输出也如我们所料,只有监听2能搜到事件,且信号都只发送一次。
2016-12-18 21:54:34.527911 TestRAC4[745:415500] start ...
2016-12-18 21:54:34.634711 TestRAC4[745:415500] producer send package 1 ...
2016-12-18 21:54:34.637899 TestRAC4[745:415500] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 21:54:34.638067 TestRAC4[745:415500] producer send package 2 ...
2016-12-18 21:54:34.638146 TestRAC4[745:415500] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 21:54:34.638195 TestRAC4[745:415500] producer send package 3 ...
2016-12-18 21:54:34.638334 TestRAC4[745:415500] Subscriber 1 get a next value: .Success(package 3)
缓冲 buffer
通过SignalProducer.buffer()创建,是一个事件的队列(通常指定数量),当新信号产生时,会重新执行队列里的事件。和pipe相似,这个方法返回一个观察者。每个发给这个观察者的事件会被加入队列。如果这个缓冲区已经达到创建时预定的数量,当新的事件发来时,最早的一个会被移出队列。
如果使用buffer来处理呢?我们将上面的冷信号稍作修改:
func generateSignal() -> SignalProducer<String, NSError> {
let (producer, observer) = SignalProducer<String, NSError>.buffer(Int.max)
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
NSLog("producer send package 1 ...")
observer.sendNext("package 1")
NSLog("producer send package 2 ...")
observer.sendNext("package 2")
NSLog("producer send package 3 ...")
observer.sendNext("package 3")
}
return producer
}
输出发现,似乎冷信号变成了热信号了,只发送了一次。但又具有冷信号的特点:两个监听器都能收到事件。
2016-12-18 21:44:29.971493 TestRAC4[740:413482] start ...
2016-12-18 21:44:31.071352 TestRAC4[740:413482] producer send package 1 ...
2016-12-18 21:44:31.075839 TestRAC4[740:413482] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 21:44:31.076115 TestRAC4[740:413482] producer send package 2 ...
2016-12-18 21:44:31.076580 TestRAC4[740:413482] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 21:44:31.076773 TestRAC4[740:413482] producer send package 3 ...
2016-12-18 21:44:31.077035 TestRAC4[740:413482] Subscriber 1 get a next value: .Success(package 3)
2016-12-18 21:44:31.078167 TestRAC4[740:413482] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 21:44:31.078420 TestRAC4[740:413482] Subscriber 2 get a next value: .Success(package 2)
2016-12-18 21:44:31.078771 TestRAC4[740:413482] Subscriber 2 get a next value: .Success(package 3)
buffer(Int.max)这里的参数表示这个缓冲大小,如果设置为1,那么第二个next发出时,缓存里第一个就被替换成了第二个next,第三个来时同理。对于第一个监听者它能收到全部事件;对于第二个监听者只能收到缓存里的事件也就是最后的package 3。如果这第一个监听者在发出信号之后再开始监听,那么它也将和第二个监听者一样只能收到缓冲里的事件。
replayLazily
假如我们不能修generateSignal()里的代码,这是由第三方提供的,我们可以使用replayLazily。
let producer = generateSignal().replayLazily(Int.max) // 直接用之前的冷信号
producer.startWithResult { NSLog("Subscriber 1 get a next value: \($0)") }
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
producer.startWithResult { NSLog("subscriber 2 get a next value: \($0)") }
}
输出如下,和buffer是一样的效果:
2016-12-18 22:04:48.364076 TestRAC4[753:417953] start ...
2016-12-18 22:04:48.482124 TestRAC4[753:417953] producer send package 1 ...
2016-12-18 22:04:48.484271 TestRAC4[753:417953] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 22:04:48.484422 TestRAC4[753:417953] producer send package 2 ...
2016-12-18 22:04:48.484665 TestRAC4[753:417953] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 22:04:48.484852 TestRAC4[753:417953] producer send package 3 ...
2016-12-18 22:04:48.485120 TestRAC4[753:417953] Subscriber 1 get a next value: .Success(package 3)
2016-12-18 22:04:49.454274 TestRAC4[753:417953] subscriber 2 get a next value: .Success(package 1)
2016-12-18 22:04:49.454659 TestRAC4[753:417953] subscriber 2 get a next value: .Success(package 2)
2016-12-18 22:04:49.454897 TestRAC4[753:417953] subscriber 2 get a next value: .Success(package 3)
那么replayLazily(Int.max)这个参数和buffer的相同吗?我们修改成1或2一看就知道。答案是相同
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。