文档地址:Basic Operators
注意本文所提的『操作符』,指的是操作signals和signal producers的函数,不是传统编程语言里的操作符。换句话说,这些是用于处理事件流的基本元素。
本文将用事件流(event stream)指代Signal和SignalProducer。当有分歧时,会单独指明类型。
本文将介绍:observe、on、lift、map、filter、reduce 六个操作符。
我翻译的RAC4的文档
ReactiveCocoa 4 官方文档翻译
ReactiveCocoa 4 文档翻译:基本操作符(一)
ReactiveCocoa 4 文档翻译:基本操作符(二)
ReactiveCocoa 4 文档翻译:框架组成介绍
ReactiveCocoa 4 文档翻译:兼容Objective-C
ReactiveCocoa 4 文档翻译--设计指南(一):事件的规范
ReactiveCocoa 4 文档翻译:设计指南(二):信号的规范
[翻译]ReactiveCocoa 4 最佳实践
对事件流产生副作用(Performing side effects with event streams)
观察(Observation)
Signals可以通过<code> observe </code>函数进行观察。参数是一个<code> Observer </code>。可以观察到这个signal将来每次发送的事件。
<pre><code>
signal.observe(Signal.Observer { event in
switch event {
case let .Next(next):
print("Next: (next)")
case let .Failed(error):
print("Failed: (error)")
case .Completed:
print("Completed")
case .Interrupted:
print("Interrupted")
}
})
</code></pre>
这样当有<code> Next, Failed, Completed</code> 和<code> Interrupted </code>事件发生时就会触发这些回调。
<pre><code>
signal.observeNext { next in
print("Next: (next)") }
signal.observeFailed { error in
print("Failed: (error)")}
signal.observeCompleted {
print("Completed") }
signal.observeInterrupted {
print("Interrupted")}
</code></pre>
你不必观察所有类型,也可以只关注某个你关心的事件。
注入影响(Injecting effects)
可以通过<code> on </code>来观察<code> SignalProducer </code>,即使没有人订阅也会被触发。
<pre><code>
let producer = signalProducer
.on(started: {
print("Started")
}, event: { event in
print("Event: (event)")
}, failed: { error in
print("Failed: (error)")
}, completed: {
print("Completed")
}, interrupted: {
print("Interrupted")
}, terminated: {
print("Terminated")
}, disposed: {
print("Disposed")
}, next: { value in
print("Next: (value)")
})
</code></pre>
和<code> observe </code>相似,也可以只观察你关注的某个事件。
需要提到的是<code> producer </code>要started后才会触发。
可能很多人不了解什么是函数的副作用,可以参考下这篇:函数的副作用
操作符合成(Operator composition)
向上迁移
<code> Signal </code>的操作符可以通过<code> lift </code>函数向上迁移以在<code>SignalProducers</code>上使用。
这样会产生一个新的SignalProducer,然后将操作符应用到每个由它产生的Signal中。
转换事件流(Transforming event streams)
以下这些操作符会将事件流转换成一个新的事件流。
映射(Mapping)
<code> map </code>用于将一个事件流的值操作后的结果产生一个新的事件流。
<pre><code>
let (signal, observer) = Signal<String, NoError>.pipe()
signal
.map { string in string.uppercaseString }
.observeNext { next in print(next) }
observer.sendNext("a") // Prints A
observer.sendNext("b") // Prints B
observer.sendNext("c") // Prints C
</code></pre>
强烈推荐这个可以到这个网站看看:Interactive visualisation of the map operator。通过了图案的方式来表达这个函数。
下图表示的是将一个数字映射为它的10倍。如果一个事件流本里的值是1、2、3,经过这个map后产生一个新的事件流,里面的值为10、20、30。
过滤(Filtering)
<code> filter </code>函数可以按照之前预设的条件过滤掉不满足的值。
<pre><code>
let (signal, observer) = Signal<Int, NoError>.pipe()
signal
.filter { number in number % 2 == 0 }
.observeNext { next in print(next) }
observer.sendNext(1) // Not printed
observer.sendNext(2) // Prints 2
observer.sendNext(3) // Not printed
observer.sendNext(4) // prints 4
</code></pre>
下图条件是x>10,最后剩下30,22,60
聚集(Aggregating)
<code> reduce </code>将事件里的值聚集后组合成一个值。要注意的是最后算出来的值直到输入的流完成后才会被发送出去。
<pre><code>
let (signal, observer) = Signal<Int, NoError>.pipe()
signal .reduce(1) { $0 * $1 }
.observeNext { next in print(next) }
observer.sendNext(1) // nothing printed
observer.sendNext(2) // nothing printed
observer.sendNext(3) // nothing printed
observer.sendCompleted() // prints 6
</code></pre>
下图展示的是输入的值为1、2、3、4、5。合并规则是求和。在5发送出去事件完成后,新的事件流将运算后求得的15发送出去。
欢迎关注我的微博:@没故事的卓同学