RxSwift

RxSwift

简介

RxSwift是什么,RxSwift是一个库,用于通过使用可观察序列和操作符来组合基于事件的异步代码,从而优化函数体的调度参数。

概念介绍

状态, 可变状态: 每个类型内部的状态, 有些是可以改变的, 改变的话会有副作用的风险

命令式编程: 就像 C 一样的指令式的, 没有方法, 只有函数, 这样就能减少其内部存储的可变的状态.

副作用: 涉及到共用的可变状态的改变, 其他用到的地方有可能会出现意料之外的情况.

声明代码:在命令式编程中,你可以随意更改状态而不会造成任何副作用。RxSwift结合了命令代码和功能代码最好的方面来为你保驾护航。

响应式系统:让UI组件根据不同的应用状态保持最新显示。组件基于消息的通信来改进,高可重用性和隔离性,将类的生命周期和实现分开,更易测试。

Observables

Observable是Rx的基础,它是泛型定义Observable,我们把它理解成一个被观察对象,它所发出的异步数据流是根据泛型T决定。Observable允许一个或多个观察者订阅,来响应事件进行逻辑并更新UI,或者处理新传入的数据等。
Observable符合ObservableType协议,它使Observable可以发射(而观察者可以接收)三种类型的事件:

next事件:此事件会携带最新值以便提供给订阅者使用。
completed事件:该事件表示成功结束事件序列。这意味着Observable成功完成了它的生命周期,从此不会再发生任何其他事件。
error事件:Observable携带出错信息终止序列,从此不会再发出其他事件。

有限的observable序列
它可以发出零个,一个或者多个值,在最后以成功或者错误而终结

无限的observable序列
说道无限序列,这就会扯到UI事件了,理想状态下它们是在一个runloop里一直无限循环等待触发。比如设备方向转换,屏幕点击,传感器触发等事件。

这里的UIDevice.rx.orientation是Rx针对UIKit的一个扩展属性,它会提供一个Observable的可观察序列,我们订阅它并根据当前的方向更新UI。我们完全可以跳过onError和onCompleted事件,因为这些事件永远不会从这个可观察的事件中发出。

操作符

Rx同流行的函数式编程一样,提供了很多基础的函数,我们只用关心输入和输出即可,一个数据流输如,输出另一个新的数据流:

1
2
3
4
5
6
7
8
9
10
UIDevice.rx.orientation
.filter { value in
return value != .landscape
}
.map { _ in
return "Portrait is the best!"
}
.subscribe(onNext: { string in
showAlert(text: string)
})

filter和map只是最基础最基础的操作函数,

Schedulers

Schedulers是Rx的调度器,它是用于任务队列调度。RxSwift附带了许多预定义的调度器,涵盖了99%的用例,所以不到万不得已你还是不要手痒自己去创建。

架构

这里非常值得一提的就是,我们并不用担心因为引入RxSwift而破坏原本架构,因为我们的Rx只是处理事件和异步数据序列。你可以继续使用MVC架构,亦或是MVP,MVVM都可以,随你喜欢。甚至你还可以选择实现自己的单向数据流架构也都中。

微软的MVVM架构是专门为在提供数据绑定的平台上创建的事件驱动软件开发的。 RxSwift和MVVM是一对好基友,在本次学习的最后我们会结合两者完成实战,以及如何使用RxSwift来实现它。
MVVM和RxSwift走得很好的原因是,ViewModel允许你公开Observable属性,这样你便能使用少量的胶水代码直接在ViewController中绑定好UIKit空间。这使得绑定模型数据到UI非常简单:

RxSwift是Swift版本的Rx的通用实现。因此,它和Cocoa,UIKit两者没有任何关系。
RxCocoa库是RxSwift的小伙伴,它是专门为UIKit和Cocoa开发的库。 除了一些高级类,RxCocoa还为许多UI组件添加响应式扩展,以便您可以订阅各种UI事件。

ref: RxSwift从零入手 - 介绍

使用

创建一个Observable

类似就是一个这样的代码

1
2
3
4
5
6
7
8
9
10
11
12
public func unifiedContacts(matching predicate: NSPredicate,
keysToFetch keys: [CNKeyDescriptor]) -> Observable<[CNContact]> {
return Observable.create { observer in
do {
observer.onNext(try self.base.unifiedContacts(matching: predicate, keysToFetch: keys))
observer.onCompleted()
} catch {
observer.onError(error)
}
return Disposables.create()
}
}

KVO 订阅一个属性

1
2
3
4
5
6
7
Observable.just(xxxx)
.flatMap {
$0.rx.observe(类型String.self, "key")
}
.subscript(onNext: {value in
xxx
})

为了防止诡异的循环引用问题, 可以定义一个 闭包的属性, 当做函数处理订阅事件

1
2
3
4
5
var foo : (bar: Int) -> () {
return { bar in
print(bar)
}
}

然后就能这样用了

1
2
3
4
Observable.just(1)
.map { $0 + 1 }
.subscribe(onNext: foo)
.addDisposableTo(disposeBag)

从 0 开始使用 RxSwift

如果感觉看了 Readme, 看了些文档后就能直接在其中的各种通用用法穿梭, 感觉….我是不行的, 即是写出来了, 也不会有思考怎么使用会好点. 还有没有其他用法, 可不可以换一种方式来简化使用, 嗯, 所以, 我还是从0 开始敲一些代码来加深自己对这种 code 模式的印象

RxSwift For Dummies 🐣 Part1

当我们创建的 Observable 是一个冷信号的时候, 只有在订阅之后才会发送信号.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
///  创建一个简单的基于 String 的 Observable
let observable = Observable<String>.create { (observer) -> Disposable in
observer.onNext("this.1")
observer.onNext("等待3秒")
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 3, execute: {
observer.onNext("this.2")
observer.onNext("this.3")
observer.onCompleted()
// complete 之后的信号不会被发射
observer.onNext("this.4")

})
// 这个 `.create` 的f方法表示在 dispose 的时候什么都不做
// return Disposables.create()
// 或者自定义一个, 声明在disposed 的时候做些什么
let disposed = Disposables.create(with: {
print("释放序列")
print("关闭数据库")
print("清楚缓存")
})
return disposed
}