Traits
Traits 是一組符合 ObservableType 的對(duì)象安疗,專門用于創(chuàng)建簡(jiǎn)單明了抄邀、易于編寫的代碼掠兄,特別是在使用UI時(shí)。
RxCocoa 的 Traits 有以下幾種規(guī)則:
- 不會(huì)產(chǎn)生
error
事件 - 一定在
MainScheduler
訂閱(主線程訂閱) - 一定在
MainScheduler
監(jiān)聽(主線程監(jiān)聽) - 它們共享資源剂癌。這并不奇怪淤翔,因?yàn)樗鼈兌际菑囊粋€(gè)叫做 SharedSequence 的實(shí)體派生出來的。
Driver
自動(dòng)得到share(replay: 1)
珍手,而Signal
得到share()
。
RxCocoa 有以下幾種 Traits:
- ControlProperty
- ControlEvent
- Driver
- Signal
你可以認(rèn)為Signal對(duì)事件建模很有用辞做,而Driver更適合對(duì)狀態(tài)建模琳要,這是因?yàn)樗鼈兊闹胤挪呗圆煌?/p>
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<String?> {
return value
}
// ...
}
ControlProperty 專門用于描述 UI 控件屬性的秤茅,它具有以下特征:
- 不會(huì)產(chǎn)生
error
事件 - 一定在
MainScheduler
訂閱(主線程訂閱) - 一定在
MainScheduler
監(jiān)聽(主線程監(jiān)聽) - 共享附加作用
ControlProperty 是一種特殊的 Subject 類型稚补,既可以發(fā)出事件,也可以接收事件框喳。
ControlEvent
打開 UIButton 下的 rx.tap 方法课幕,可以看到:
import RxSwift
import UIKit
extension Reactive where Base: UIButton {
public var tap: ControlEvent<Void> {
return controlEvent(.touchUpInside)
}
}
(1)ControlEvent 是專門用于描述 UI 所產(chǎn)生的事件,擁有該類型的屬性都是被觀察者(Observable)五垮。
(2)ControlEvent 和 ControlProperty 一樣乍惊,都具有以下特征:
- 不會(huì)產(chǎn)生 error 事件
- 一定在 MainScheduler 訂閱(主線程訂閱)
- 一定在 MainScheduler 監(jiān)聽(主線程監(jiān)聽)
- 共享狀態(tài)變化
Binder
Binder 主要有以下兩個(gè)特征:
- 不會(huì)處理錯(cuò)誤事件
- 確保綁定都是在給定 Scheduler 上執(zhí)行(默認(rèn) MainScheduler)
一旦產(chǎn)生錯(cuò)誤事件,在調(diào)試環(huán)境下將執(zhí)行 fatalError
放仗,在發(fā)布環(huán)境下將打印錯(cuò)誤信息润绎。
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 中,一個(gè) binding 是一個(gè)單向的數(shù)據(jù)流。這大大簡(jiǎn)化了應(yīng)用程序中的數(shù)據(jù)流莉撇,所以在本書中你不會(huì)涉及雙向綁定呢蛤。
What are binding observables
[圖片上傳失敗...(image-7272f3-1639451057115)]
想象一下這兩個(gè)實(shí)體以及對(duì)應(yīng)的關(guān)系:
- 一個(gè) Producer, 用來產(chǎn)生數(shù)據(jù)
- 一個(gè) Consumer, 用來處理來自 Producer 的數(shù)據(jù)
[圖片上傳失敗...(image-af2322-1639451057115)]
一個(gè) Consumer 不能返回?cái)?shù)據(jù),這是在 RxSwift 中使用 binding 的一條基本規(guī)則棍郎。
綁定的基本方法是 bind(to:)
, 用來把一個(gè) observable 綁定到另一個(gè)實(shí)體其障。這就要求 consumer 遵循 ObserverType 協(xié)議,一個(gè) write-only 的實(shí)體只能接收新數(shù)據(jù)但是不能被訂閱涂佃。
我們目前學(xué)過的遵循 ObserverType 類型的是 Subject, 它既遵循 ObserverType 又遵循 ObservableType 協(xié)議励翼,使它既可以發(fā)出事件,也可以訂閱事件巡李。
考慮到像 UILabel抚笔、UITexField、UIImageView 等基本組件都有可以設(shè)置或獲取的可變數(shù)據(jù)侨拦,在使用 Cocoa 的命令式特性時(shí)殊橙,Subjects 是非常重要的。
<aside> ?? 注意:除了符合 ObserverType 的對(duì)象之外狱从,你還可以在 Relays 上使用 bind(to:)膨蛮。那些 bind(to:) 方法是單獨(dú)的重載,因?yàn)?Relays 不符合 ObserverType季研。
</aside>
最后敞葛,一個(gè)有趣的事實(shí)是,bind(to:)
是 subscribe()
的別名与涡,或者說是語法糖惹谐。調(diào)用 bind(to: observer)
將在內(nèi)部調(diào)用 subscribe(observer)
。前者只是為了創(chuàng)造一個(gè)更有意義和直觀的語法驼卖。
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<String>
{
return Binder(self.base) { (viewController, title) in
viewController.title = title
}
}
}
output.title.bind(to: self.rx.title).disposed(by: disposeBag)
Driver 帶來一個(gè)名為 drive 的方法氨肌,只要把 bind(to:)
替換成 driver
, 就可以正常使用了。
output.title.drive(self.rx.title).disposed(by: disposeBag)