简介
它拓展了观察者模式。使你能够自由组合多个异步事件,而不需要去关心线程,同步,线程安全,并发数据以及I/O阻塞。
函数响应式编程
- 函数式编程:是种编程范式,它需要我们将函数作为参数传递,或者作为返回值返还。我们可以通过组合不同的函数来得到想要的结果。
- 响应式编程: a=b+c表示将表达式的结果赋给 a,而之后改变 b 或 c的值不会影响 a。但在响应式编程中,a的值会随着 b或 c的更新而更新。a=b+c声明的是一种绑定关系。
RxSwift优点
- 在业务层面实现代码逻辑分离,方便后期维护和拓展
- 极大提高程序响应速度,充分发掘CPU的能力
- 帮助开发者提高代码的抽象能力和充分理解业务逻辑
- Rx丰富的操作符会帮助我们极大的简化代码逻辑
核心
- Observable - 可被监听的序列产列
- Observer - 观察者
- Operator - 操作符
- Disposable - 管理绑定(订阅)的生命周期
- Schedulers - 调度器(线程队列调配)
Observable - 可被监听的序列
框架已经帮我们创建好了许多常用的序列。例如:button的点击,textField的当前文本,switch的开关状态,slider的当前数值等等。
let numbers: Observable = Observable.create { observer -> Disposable in
observer.onNext(0)
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onNext(4)
observer.onNext(5)
observer.onNext(6)
observer.onNext(7)
observer.onNext(8)
observer.onNext(9)
observer.onCompleted()
return Disposables.create()
}
Observer - 观察者
观察者最直接的方法就是在 Observable 的 subscribe 方法后面描述,事件发生时,需要如何做出响应。而观察者就是由后面的 onNext,onError,onCompleted的这些闭包构建出来的。
- observer.onNext(0) 就代表产生了一个元素,他的值是 0。
- onCompleted()结束
- onError()发生错误
tap.subscribe(onNext: { [weak self] in
self?.showAlert()
}, onError: { error in
print("发生错误: \(error.localizedDescription)")
}, onCompleted: {
print("任务完成")
})
操作符
- filter - 过滤
// 温度
let rxTemperature: Observable = ...
// filter 操作符
rxTemperature.filter { temperature in temperature > 33 }
.subscribe(onNext: { temperature in
print("高温:\(temperature)度")
})
.disposed(by: disposeBag)
- map - 转换
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.map { $0 * 10 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
- zip - 配对
let disposeBag = DisposeBag()
let first = PublishSubject()
let second = PublishSubject()
Observable.zip(first, second) { $0 + $1 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
first.onNext("1")
second.onNext("A")
1A
Disposable - 可被清除的资源
通常来说,一个序列如果发出了 error 或者 completed 事件,那么所有内部资源都会被释放。如果你需要提前释放这些资源或取消订阅的话,那么你可以对返回的 可被清除的资源(Disposable) 调用 dispose 方发
通常情况下,我们不需要手动调用 dispose 方法的
使用 清除包(DisposeBag) 或者 takeUntil 操作符 来管理订阅的生命周期
- DisposeBag - 清除包
var disposeBag = DisposeBag()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
textField.rx.text.orEmpty
.subscribe(onNext: { text in print(text) })
.disposed(by: self.disposeBag)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.disposeBag = DisposeBag()
}
- takeUntil
使得订阅一直持续到控制器的 dealloc 事件产生为止
override func viewDidLoad() {
super.viewDidLoad()
...
_ = usernameValid
.takeUntil(self.rx.deallocated)
.bind(to: passwordOutlet.rx.isEnabled)
_ = usernameValid
.takeUntil(self.rx.deallocated)
.bind(to: usernameValidOutlet.rx.isHidden)
_ = passwordValid
.takeUntil(self.rx.deallocated)
.bind(to: passwordValidOutlet.rx.isHidden)
_ = everythingValid
.takeUntil(self.rx.deallocated)
.bind(to: doSomethingOutlet.rx.isEnabled)
_ = doSomethingOutlet.rx.tap
.takeUntil(self.rx.deallocated)
.subscribe(onNext: { [weak self] in self?.showAlert() })
}
Schedulers - 调度器
Schedulers 是 Rx 实现多线程的核心模块,它主要用于控制任务在哪个线程或队列运行。
GCD:
// 后台取得数据,主线程处理结果
DispatchQueue.global(qos: .userInitiated).async {
let data = try? Data(contentsOf: url)
DispatchQueue.main.async {
self.data = data
}
}
RxSwift:
let rxData: Observable = ...
rxData
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] data in
self?.data = data
})
.disposed(by: disposeBag)
subscribeOn 来决定数据序列的构建函数在哪个 Scheduler 上运行。以上例子中,由于获取 Data 需要花很长的时间,所以用 subscribeOn 切换到 后台 Scheduler 来获取 Data。这样可以避免主线程被阻塞。
observeOn 来决定在哪个 Scheduler 监听这个数据序列。以上例子中,通过使用 observeOn 方法切换到主线程来监听并且处理结果。
MainScheduler 主线程
SerialDispatchQueueScheduler
抽象了串行 DispatchQueue。如果你需要执行一些串行任务,可以切换到这个 Scheduler 运行。ConcurrentDispatchQueueScheduler
抽象了并行 DispatchQueue。如果你需要执行一些并发任务,可以切换到这个 Scheduler 运行。OperationQueueScheduler 抽象了 NSOperationQueue。它具备 NSOperationQueue 的一些特点,例如,你可以通过设置 maxConcurrentOperationCount,来控制同时执行并发任务的最大数量。
Error Handling - 错误处理
RxSwift 主要有两种错误处理机制:
- retry - 重试
- catch - 恢复
retry - 重试
- retry
let rxJson: Observable = ...
rxJson
.retry(3)
.subscribe(onNext: { json in
print("取得 JSON 成功: \(json)")
}, onError: { error in
print("取得 JSON 失败: \(error)")
})
.disposed(by: disposeBag)
失败后重试三次
- retryWhen
操作符,这个操作符主要描述应该在何时重试,并且通过闭包里面返回的 Observable 来控制重试的时机:
let maxRetryCount = 4 // 最多重试 4 次
let retryDelay: Double = 5 // 重试延时 5 秒
rxJson
.retryWhen { (rxError: Observable) -> Observable in
return rxError.flatMapWithIndex { (error, index) -> Observable in
guard index < maxRetryCount else {
return Observable.error(error)
}
return Observable.timer(retryDelay, scheduler: MainScheduler.instance)
}
}
.subscribe(...)
.disposed(by: disposeBag)
catchError - 恢复
- catchError
可以在错误产生时,用一个备用元素或者一组备用元素将错误替换掉:
let rxData: Observable = ... // 网络请求的数据
let cahcedData: Observable = ... // 之前本地缓存的数据
rxData
.catchError { _ in cahcedData }
.subscribe(onNext: { date in
print("获取数据成功: \(date.count)")
})
.disposed(by: disposeBag)
- catchErrorJustReturn 当错误产生时,就返回一个空数组,于是就会显示一个空列表页。
Result
展示错误结果
updateUserInfoButton.rx.tap
.withLatestFrom(rxUserInfo)
.flatMapLatest { userInfo -> Observable> in
return update(userInfo)
.map(Result.success) // 转换成 Result
.catchError { error in Observable.just(Result.failure(error)) }
}
.observeOn(MainScheduler.instance)
.subscribe(onNext: { result in
switch result { // 处理 Result
case .success:
print("用户信息更新成功")
case .failure(let error):
print("用户信息更新失败: \(error.localizedDescription)")
}
})
.disposed(by: disposeBag)
其他
后面会讲下具体实践-UI上的使用,还有更多理论性的东西就看文档就ok了,操作符遇到了再查。
基本常用控件
UITablView和UICollectionview使用
其他不常用控件
所有例子demo
参考文献
swift开发
RxSwift中文文档