RxSwift
RxSwift的目的是让让数据/事件流和异步任务能够更方便的序列化处理,能够使用Swift进行响应式编程。RxSwift把我们程序中每一个操作都看成一个事件,比如一个TextField中的文本改变,一个按钮被点击,或者一个网络请求结束等,每一个事件源就可以看成一个序列,也就是sequence,比如TextField,当我们改变里面的文本的时候,这个TextField就会不断的发出事件,从他的这个sequence中不断的流出,我们只需要监听这个sequence,每流出一个事件就做相应的处理。同理,Button也是一个sequence,每点击一次就流出一个事件。也就是我们把每一步都想成是一个事件就好去理解RxSwift了,可以配合下图理解:
Observables/Sequences
先复习下SequenceType。这是Swift中的一个协议,比如Swift中的Array就遵循这个协议,通过这个协议,你可以这样的去操作一个Array:
let array = [1,2,3,4,5]
let array2 = array.filter({$0 > 1}).map({$0 * 2})//4 6 8 10
var indexGenerator = array2.makeIterator()
let fisrt = indexGenerator.next() // 4
let seoncd = indexGenerator.next() //6
也就是说,把Array作为一个序列,然后依次对这个序列进行过滤,映射等操作,也可以通过indexGenerator来一个个的获取序列中的数据。RxSwift的核心思想和这个类似。RxSwift的核心是想是 Observable<Element> sequence,Observable sequence就是一个sequence,Observable表示可监听或者可观察,也就是说RxSwift的核心思想是可监听的序列。并且,Observable sequence可以接受异步信号,也就是说,信号是可以异步给监听者的:
1 Observable(ObservableType) 和 Sequence类似
2 ObservableType.subscribe方法等同于Sequence.makeIterator
3 Observer (callback)需要被传递到ObservableType.subscribe方法来接受sequence elements而不是调用next()。
可观察序列类型(observable sequences)
有限观察序列(Finite observable sequences)
可观察序列能够发送0,1,或者多个值,当到达某一个点时,有可能是可观察序列发送完成事件,也有可能是发送事件时发生错误而导致发送事件终止。
在iOS应用中,考虑下载文件的情况:
1 首先,你开始下载并且观察即将接收的数据
2 重复接收文件的数据
3 如果网络连接出现问题,有可能下载将停止并且连接超时,发生错误
4 也有可能文件已经下载完成,那么下载完成
上面工作流的精准描述了可观察对象(observable)的生命周期,如下代码所示:
API.download(file: "http://www...")
.subscribe(onNext: { data in
... append data to temporary file
},
onError: { error in
... display error to user
},
onCompleted: {
... use downloaded file
})
无限观察序列(Infinite observable sequences)
不像文件下载或者一些相似的操作,这些都应该自然或者强制终止。有一些序列是无限执行的,比如:UI事件就是无限观察序列。
例如:app中响应设备方向的改变。你添加你的类作为观察者,监听设备方向改变通(UIDeviceOrientationDidChange),而且你需要提供对应的方法回调来处理设备方向改变。对于设备方向的改变并不会自然结束,只要设备存在,就有可能方向发生改变。近一步,可以模拟为序列的几乎是无限的,一直处于观察。注意:如果用户的设备从未旋转,这并不意味着事件序列终止,只是说明没有事件被发送(events emitted)。
在RxSwift,我们可能写如下代码处理设备的方向:
UIDevice.rx.orientation
.subscribe(onNext: { current in
switch current {
case .landscape:
... re-arrange UI for landscape
case .portrait:
... re-arrange UI for portrait
}
})
UIDevice.rx.orientation是虚构的控制权属性,主要是获得Observable<Orientation>。然后对获得对象进行订阅(subscribe),根据设备的方向更新UI.这里省略了onError和onCompleted参数,因为这些事件从未被发送。
Operators
Observable类中包含了大量的方法能够被用于抽象分离异步工作,通过组合这些方法能够实现复杂的逻辑。由于各个部分高度的解耦,这些方法经常被引用作为操作符(Operators)。因为这些Operators大多数都能够执行异步输入,它们能够很好的组装在一起,就像拼图的一块,能够组合出更大的图片。相似的,我们可以使用Rx操作符(Operators)拼接各个部分,由被观察者(Observable)来确定输入和输出的过程,看前面设备方向的使用例子:
UIDevice.rx.orientation
.filter { value in
return value != .landscape
}
.map { _ in
return "Portrait is the best!"
}
.subscribe(onNext: { string in
showAlert(text: string)
})
每次UIDevice.rx.orientation产生一个.landscape或.portrait值,Rx将使用一些operators来执行数据操作。流程图如下:
1 首先filter操作符将对值进行过滤,如果值不等于.landscape将通过。如果设备是.landscape
模式,订阅者部分代码将不会执行,因为filter操作符将阻止事件。
2 如果是.portrait值,mapoperator将设备输入的类型转换为字符串输出,文本内容为"Portrait is the best!"
3 最终,订阅者将执行next事件,在闭包中调用显示弹框方法
operators是高度的可组合,它们将数据作为数据并且输出对应的结果,所以我们能够很容易以不同的方式链式使用它们,而且比使用单一operators效果好