一个信号发生器,由
SignalProducer
类型表示,可以创建信号(signals
)并施加副作用(side effects
)。
信号发生器用来表示操作或者任务,比如网络请求,每一次对它调用
start()
将会生成一个新的后台操作,并允许调用者监视它的结果。另一种形式的startWithSignal()
方法,会给出产生的信号,允许在必要的情况下被监听多次。
根据
start()
方法的动作方式,被同一个信号发生器生成的信号可能会有不同的事件顺序或版本,甚至事件流完全不一样!和普通的信号不同,在监听器连接上之前,信号发生器不会开始工作(也就没有事件会生成),并且在每一个新的监听器连接上时其工作都会重新开始。
启动一个信号发生器会返回一个存根(
disposable
),它可用来打断或取消被生成信号的工作。
和信号一样,信号生成器可以通过
map
、filter
等原函数操作。使用lift
方法,所有信号的原函数可以被提升成为以信号生成器为对象的操作。除此以外,还有一些用来控制何时与如何启动信号生成器的原函数,比如times
。
1. 信号发生器什么样
简单地讲,信号发生器就是一个制造信号的方法。在信号发生器内部,这个方法称为启动处理器(startHandler),它是信号发生器仅有的数据成员:
public struct SignalProducer<Value, Error: ErrorType> {
public typealias ProducedSignal = Signal<Value, Error>
private let startHandler: (Signal<Value, Error>.Observer, CompositeDisposable) -> ()
......
}
也就是说,信号发生器看起来是这样的:
2. 创建信号发生器
信号发生器的初始化函数同样十分简单,就是将我们提供的参数作为启动处理器保存起来:
public struct SignalProducer<Value, Error: ErrorType> {
......
public init(_ startHandler: (Signal<Value, Error>.Observer, CompositeDisposable) -> ()) {
self.startHandler = startHandler
}
......
}
为了更顺利地讨论后面的内容,我们在此约定:信号发生器制造出来的信号称为结果信号(produced signal)。
现在要看看我们的任务了:定义启动处理器。启动处理器的主要内容,就是定义结果信号的事件源。它会在信号发生器每次启动时被调用,也就是说,结果信号只有在信号发生器启动时才会生成,而且每一次启动信号生成器都会得到一个新的结果信号,只不过这些结果信号的事件源工作方式相同(但产生的事件不一定相同)。
启动处理器是一个签名为(Observer, CompositeDisposable) -> ()
的方法,第一个参数就是结果信号(即将被制造的信号)的事件分发器,如果我们向这个分发器发送事件的话,结果信号的监听器就会收到。
3. 启动信号发生器
启动信号发生器,可以调用信号发生器对象的startWithSignal(setUp: (Signal, Disposable) -> ())
方法,这个方法接收一个回调函数作为参数,而我们必须提供这个回调函数。正如参数名称setUp所暗示的,这个回调函数会在信号的事件源开始工作(也就是发送事件)之前执行,信号的引用和一个取消用存根被交到我们手中,这给了我们一个机会做一些准备工作,比如向信号添加监听器,将信号变形,或者干脆通过取消用存根取消启动等等。
下面是startWithSignal执行的步骤:
- 调用Signal类的pipe()类方法,得到一个信号和这个信号的事件分发器。
- 创建一个CompositeDisposable类型的发生器存根。
- 创建一个ActionDisposable类型的取消用存根,如果这个存根被废弃,它会在事件分发器上发送一个Interrupted事件,之后将上一步中创建的发生器存根废弃掉。
- 将信号和取消用存根交给回调方法setUp,执行我们的准备工作。
- 如果准备工作后取消用存根被废弃了,就停止处理立即返回。
- 将信号的事件分发器包装在一个监听器对象(wrapperObserver)中,这个监听器对象会将自己接收到的所有事件原封不动地交给事件分发器,不过一旦它接收到终结事件,它会废弃第二步中创建的生成器存根。
- 使用上一步包装过的监听器和第二步中创建的发生器存根调用启动处理器。
4. 缓冲(Buffer)
缓冲,由
SignalProducer.buffer()
方法创建,是一个事件的队列(queue),每当信号发生器创建新的信号时,队列中的事件会被重播(replay)。
和管道(
pipe
)相似,这个方法返回一个监听器(Observer)。向这个监听器发送的事件会被加入队列中。如果在加入新的事件时,队列已经达到最大容量(队列长度),那么为了以腾出空间,队列中最早加入的事件会被移除。