Traits
Traits 是一组符合 ObservableType 的对象,专门用于创建简单明了、易于编写的代码,特别是在使用UI时。
RxCocoa 的 Traits 有以下几种规则:
- 不会产生
error
事件 - 一定在
MainScheduler
订阅(主线程订阅) - 一定在
MainScheduler
监听(主线程监听) - 它们共享资源。这并不奇怪,因为它们都是从一个叫做 SharedSequence 的实体派生出来的。
Driver
自动得到share(replay: 1)
,而Signal
得到share()
。
RxCocoa 有以下几种 Traits:
- ControlProperty
- ControlEvent
- Driver
- Signal
你可以认为Signal对事件建模很有用,而Driver更适合对状态建模,这是因为它们的重放策略不同。
You can think of Signal as useful for modeling events, where a Driver is more suitable for modeling state, due to their different replay strategies.
ControlProperty
打开 UITextField+Rx.swift 文件,我们可以看到以下代码:
extension Reactive where Base: UITextField {
/// Reactive wrapper for `text` property.
public var text: ControlProperty {
return value
}
// ...
}
ControlProperty 专门用于描述 UI 控件属性的,它具有以下特征:
- 不会产生
error
事件 - 一定在
MainScheduler
订阅(主线程订阅) - 一定在
MainScheduler
监听(主线程监听) - 共享附加作用
ControlProperty 是一种特殊的 Subject 类型,既可以发出事件,也可以接收事件。
ControlEvent
打开 UIButton 下的 rx.tap 方法,可以看到:
import RxSwift
import UIKit
extension Reactive where Base: UIButton {
public var tap: ControlEvent {
return controlEvent(.touchUpInside)
}
}
(1)ControlEvent 是专门用于描述 UI 所产生的事件,拥有该类型的属性都是被观察者(Observable)。
(2)ControlEvent 和 ControlProperty 一样,都具有以下特征:
- 不会产生 error 事件
- 一定在 MainScheduler 订阅(主线程订阅)
- 一定在 MainScheduler 监听(主线程监听)
- 共享状态变化
Binder
Binder 主要有以下两个特征:
- 不会处理错误事件
- 确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler)
一旦产生错误事件,在调试环境下将执行 fatalError
,在发布环境下将打印错误信息。
It also takes care of weakifying and retaining its base object, so you don't have to deal with pesky memory leaks or weak references.
Binding observables
在 RxCocoa 中,一个 binding 是一个单向的数据流。这大大简化了应用程序中的数据流,所以在本书中你不会涉及双向绑定。
What are binding observables
[图片上传失败...(image-7272f3-1639451057115)]
想象一下这两个实体以及对应的关系:
- 一个 Producer, 用来产生数据
- 一个 Consumer, 用来处理来自 Producer 的数据
[图片上传失败...(image-af2322-1639451057115)]
一个 Consumer 不能返回数据,这是在 RxSwift 中使用 binding 的一条基本规则。
绑定的基本方法是 bind(to:)
, 用来把一个 observable 绑定到另一个实体。这就要求 consumer 遵循 ObserverType 协议,一个 write-only 的实体只能接收新数据但是不能被订阅。
我们目前学过的遵循 ObserverType 类型的是 Subject, 它既遵循 ObserverType 又遵循 ObservableType 协议,使它既可以发出事件,也可以订阅事件。
考虑到像 UILabel、UITexField、UIImageView 等基本组件都有可以设置或获取的可变数据,在使用 Cocoa 的命令式特性时,Subjects 是非常重要的。
最后,一个有趣的事实是,bind(to:)
是 subscribe()
的别名,或者说是语法糖。调用 bind(to: observer)
将在内部调用 subscribe(observer)
。前者只是为了创造一个更有意义和直观的语法。
Using binding observables to display data
output.title.subscribe(onNext :{title in
self.title = title
})
.disposed(by: disposeBag)
// 使用 bind
extension Reactive where Base:UIViewController
{
public var title : Binder
{
return Binder(self.base) { (viewController, title) in
viewController.title = title
}
}
}
output.title.bind(to: self.rx.title).disposed(by: disposeBag)
Driver 带来一个名为 drive 的方法,只要把 bind(to:)
替换成 driver
, 就可以正常使用了。
output.title.drive(self.rx.title).disposed(by: disposeBag)
参考资料
https://www.hangge.com/blog/cache/detail_1943.html
http://anbig.com/2020/10/21/rxswift-binder/