官方文档:
http://reactivecocoa.io/reactiveswift/docs/latest/index.html
实战项目:
https://github.com/JornWu/ZhiBo_Swift.git
1、Events
一个事件,由代表Event类型,是一个事实,即抽象化表示事情发生。在ReactiveSwift中,事件是沟通的核心。事件可能表示按下按钮,从API接收到的信息,发生错误,或者完成长时间运行的操作。
无论如何,某些事物会产生事件,并通过信号将其发送给任何数量的观察者。
Event
是一个枚举类型,表示一个值或三个终止事件之一:
-
value
事件
表示源提供了一个新的值。 -
failed
事件
表示之前的事件发出了错误。事件由参数为ErrorType
类型,它决定了允许在事件中出现的故障类型。
如果不允许发生故障,则事件可以使用NoError
类型来防止提供任何错误。 -
completed
事件
表示信号已成功完成,并且没有更多的值由源发送了。 -
interrupted
事件
表示信号已经终止,因为它是取消,这意味着操作既不是成功也不是不成功
2、Signals
信号,由Signal所表示的类型,随着时间的推移可以观察到任何系列的事件。
Signal
通常用于表示已在“进行中”的Event Stream
,如通知,用户输入等。在执行工作或接收到数据时,会发送事件信号,将其推送给任何观察者且所有观察员同时看到事件。
用户必须observer信号才能访问其事件。观察信号不会触发任何Side Effect
。换句话说,信号完全是由生产者为主导,推送式的,消费者(观察者)对其“一生”不会有任何影响。在观察信号时,用户只能按照与信号发送相同的顺序来评估事件。不能随机访问信号的值。
可以通过对它们应用primitives来操纵信号。用于操纵单个信号的典型primitives
如可用 filter
,map
和reduce
以及用于一次操纵多个信号的primitives
(zip
)。primitives
只对value
信号的事件进行操作。
Signal
的寿命由若干数量的value
事件接着是一个终止事件构成,该终止事件可以是中的任一项failed
,completed
或 interrupted
(但不是组合)。终止事件不包括在信号的值中它们必须特别处理。
3、Pipes
Pipe
,通过创建Signal.pipe()
,是一个可以被手动控制的信号。该方法返回信号和观察者。可以通过向观察者发送事件来控制信号。这对于将非RAC代码桥接到信号界非常有用。例如,块可以简单地向观察者发送事件来代替在块回调中的应用程序逻辑的处理。同时,可以返回信号和隐藏回调的实现细节。
4、Signal Producers
signal producer
,是SignalProducer
类型的实例,它可以创建信号(signals
)并施加附作用(side effects
)。
signal producer
用来表示操作或者任务,比如网络请求,每一次对它调用start()
将会生成一个新的潜在操作,并允许调用者观察它的结果。还有一个startWithSignal()
方法,会给出产生的信号,允许在必要的情况下被监听多次。
根据start()
方法的动作方式,被同一个信号发生器生成的信号可能会有不同的事件顺序或版本,甚至事件流完全不一样!和普通的信号不同,在观察者订阅上之前,信号发生器不会开始工作(也就没有事件会生成),并且在每一个新的观察者订阅上时其工作都会重新开始一个单独的工作流。
启动一个signal producer
会返回一个销毁器(disposable
),它可用来打断或取消信号的工作。
和Signal
一样,signal producer
可以通过map
、filter
等原函数操作。使用lift
方法,所有Signal
的primitives
可以被转换成为以signal producer
为对象的操作。除此以外,还有一些用来控制何时与如何启动signal producer
的primitives
,比如times
。
5、Observers
observer
是什么,是正在等待或可以等待从信号发出的事件的对象。
在RAC中,observer
表示为接受Event值的Observer。可以通过使用Signal.observe
或SignalProducer.start
的方法基于回调的形式隐式创建观察者 。
6、Lifetimes
当观察信号或启动信号发生器时,重要的是考虑观察应该持续多久。例如,当观察信号以更新UI组件时,一旦组件不再在屏幕上,停止观察它是有意义的。这个想法在ReactiveSwift中由Lifetime
类型表示。
import Foundation
final class SettingsController {
// Define a lifetime for instances of this class. When an instance is
// deinitialized, the lifetime ends.
private let (lifetime, token) = Lifetime.make()
func observeDefaultsChanged(_ defaults: UserDefaults = .standard) {
// `take(during: lifetime)` ensures the observation ends when this object
// is deinitialized
NotificationCenter.default.reactive
.notifications(forName: UserDefaults.didChangeNotification, object: defaults)
.take(during: lifetime)
.observeValues { [weak self] _ in self?.defaultsChanged(defaults) }
}
private func defaultsChanged(_ defaults: UserDefaults) {
// perform some updates
}
}
这token
是一个Lifetime.Token
,我们需要保持强引用,以便Lifetime
工作。(注意:至关重要的是只有一个强引用token
,因此它在同一时间被初始化为self
。)
Lifetime
任何时候观察可能比观察者更为有用:
1、 在NotificationCenter
上面的例子中,没有Lifetime
观察将永远不会完成(泄露内存并浪费CPU周期)。
2、考虑一个触发网络请求的信号发生器 -Lifetime
如果观察器被初始化,则结合一个可能允许自动取消该请求。
7、Actions
action
由Action类型表示,在执行输入时处理某些工作。在执行中,可能会产生零个或多个输出值和/或失败。
Actions
对于在用户交互中执行side-effecting
很有用,例如单击按钮时。也可以根据properties自动禁用Actions
,且该禁用状态可以表示到UI中等同于禁用与Actions
相关联的任何控件。
8、Properties
property由PropertyProtocol表示,其存储某个值,并通知观察者关于该值的未来将会变化。
属性的当前值可以从value
getter
中获得。该producer
getter
返回一个信号产生器,将发送属性的当前值,然后随着时间的推移而变化的所有更改值。该signal getter
返回一个信号,将发送随着时间的所有变化的值,而不是初始值。
<~
操作可用于用不同的方式绑定属性。
请注意,在所有情况下,由BindingTargetProtocol表示的目标必须是绑定状态目标。
由MutablePropertyProtocol表示的所有可变属性类型都是固有的绑定目标。
-
property <~ signal
将信号绑定到属性,将属性值更新为信号发送的最新值。 -
property <~ producer
启动给定的信号生成器,并将属性的值绑定到启动信号上发送的最新值。 -
property <~ otherProperty
将一个属性绑定到另一个属性,以便在更新源属性时更新目标属性的值。
属性提供了许多的变换如map
,combineLatest
或zip
的处理类似于信号和信号产生器
9、Disposables
disposable
,由Disposable协议表示,是用于存储器管理和消除的机制。当启动信号发生器时,将返回disposable
。调用者可以使用该disposable
功能来取消已经开始的工作(例如后台处理,网络请求等),清理所有临时资源,然后interrupted
根据创建的特定
信号发送最终事件 。观察信号也可能返回disposable
。处理它会阻止观察者从该信号中收到任何未来的事件,但对信号本身不会有任何影响。有关取消的更多信息,请参阅RAC 设计指南。
10、Schedulers
scheduler
,由SchedulerProtocol协议所表示,是执行工作或在递送Value
的串行执行队列。信号和信号发生器可以被放到特定调度器上传送事件。信号生成器 还可以被放到特定调度器上开始工作。
Schedulers
类似于Grand Central Dispatch
队列,但Schedulers
支持取消(通过disposables),并且始终连续执行。除了ImmediateScheduler,Schedulers
不提供同步执行。这有助于避免死锁,并鼓励使用signal and signal producer primitives ,而不是阻止工作。
Schedulers
也有些类似NSOperationQueue
,但Schedulers
不允许任务重新排序或相互依赖。