Subjects 介紹
Subjects
是訂閱者旷余,也是Observable
:
訂閱者:它能動態(tài)的接收新的值。
Observable: 當(dāng)Subjects有了新值后會通過Event將新值發(fā)出給他的所有訂閱者扁达。
Subjects
有四種:PublishSubject正卧、BehaviorSubject、ReplaySubject跪解、Variable
相同點(diǎn)
都是Observable炉旷,他們的訂閱者都能接收他們發(fā)出的新的Event
直到 Subject 發(fā)出 .complete 或者 .error 的 Event 后,該 Subject 便終結(jié)了叉讥,同時(shí)它也就不會再發(fā)出.next事件窘行。
在Subject 終結(jié)后再訂閱他的訂閱者,也能收到 subject發(fā)出的一條.complete 或.error的event图仓,
不同點(diǎn)
PublishSubject
最普通的Subject罐盔,不需要初始值就能初始化。
他的訂閱者只能收到他們訂閱后的 Event救崔。
enum MyError: Error {
case A
case B
var errorType: String {
switch self {
case .A:
return "error A"
case .B:
return "error B"
}
}
}
let disposeBag = DisposeBag()
PublishSubject
將發(fā)送訂閱后產(chǎn)生的元素惶看,而之前元素將不會發(fā)送給觀察者
結(jié)束
之后添加的訂閱能收到 completed
結(jié)束
后發(fā)的都收不到
func testPublishSubject() {
let publicSubject = PublishSubject<Int>()
publicSubject.onNext(1) //沒有輸出
publicSubject.subscribe { e in
print(e.element ?? 0)
}.disposed(by: disposeBag)
publicSubject.onNext(2) //輸出:2
publicSubject.onNext(3) //輸出:3
publicSubject.onCompleted() //輸出:0
publicSubject.subscribe { event in
print(event)
}.disposed(by: disposeBag) //輸出:completed
publicSubject.onNext(4) //無
}
AsyncSubject
將在源 Observable 產(chǎn)生完成事件后,發(fā)出最后一個(gè)元素(僅僅只有最后一個(gè)元素)六孵,
如果源 Observable 沒有發(fā)出任何元素纬黎,只有一個(gè)完成事件
func testAsyncSubject() {
let asyncSubject = AsyncSubject<String>()
asyncSubject.subscribe { e in
print((e.element ?? "xx") as String)
//print(e.element)
}.disposed(by: disposeBag)
asyncSubject.onNext("A")
asyncSubject.onNext("B")
asyncSubject.onNext("C") //執(zhí)行
asyncSubject.onCompleted()//執(zhí)行
//輸出:
//C
//xx
}
AsyncSubject
如果源 Observable 因?yàn)楫a(chǎn)生了一個(gè) error 事件而中止,
就不會發(fā)出任何元素劫窒,而是將這個(gè) error 事件發(fā)送出來
func testAsyncError() {
let asyncSubject = AsyncSubject<String>()
asyncSubject.subscribe { e in
print(e)
}.disposed(by: disposeBag)
asyncSubject.onNext("A1")
asyncSubject.onNext("B1")
asyncSubject.onNext("C1")
asyncSubject.onError(MyError.A) //執(zhí)行
asyncSubject.onCompleted()
//輸出:
//error(A)
}
ReplaySubject
將發(fā)送全部的元素本今,無論是何時(shí)進(jìn)行訂閱的
結(jié)束后訂閱
,不僅會收到最后的n個(gè) event 還有 Completed
func testReplaySubject() {
//多個(gè)版本的 ReplaySubject主巍,有的只會將最新的 n 個(gè)元素發(fā)送給觀察者冠息,有的只會將 限制時(shí)間段內(nèi) 最新的元素發(fā)送給觀察者
//如果把 ReplaySubject 當(dāng)作觀察者來使用俺孙,注意不要在多個(gè)線程調(diào)用 onNext, onError 或 onCompleted霉晕。這樣會導(dǎo)致無序調(diào)用刁憋,將造成意想不到的結(jié)果
let replaySubject = ReplaySubject<String>.create(bufferSize: 2)
replaySubject.onNext("1")
replaySubject.onNext("2")
replaySubject.onNext("3")
replaySubject.subscribe { (e) in
print(e.element ?? "")
}.disposed(by: disposeBag)
replaySubject.onNext("A")
replaySubject.onNext("B")
replaySubject.onNext("C")
replaySubject.onCompleted()
print("-------")
/// 不僅會收到最后的兩個(gè) event 還有 Completed
replaySubject.subscribe { event in
print("訂閱4", event)
}.disposed(by: disposeBag)
//輸出:
/**
2
3
A
B
C
-------
訂閱4 next(B)
訂閱4 next(C)
訂閱4 completed
*/
}
BehaviorSubject
它會將最新的元素 發(fā)送出來(如果不存在最新的型宙,就發(fā)出默認(rèn)元素)风钻。
需要一個(gè)默認(rèn)值初始化
當(dāng)一個(gè)訂閱者
訂閱之后會立馬收到上一個(gè)Event柴灯,之后就是正常情況發(fā)一個(gè)收一個(gè)
func testBehaviorSubject() {
//如果源 Observable 因?yàn)楫a(chǎn)生了一個(gè) error 事件而中止盗尸, BehaviorSubject 就不會發(fā)出任何元素麸祷,而是將這個(gè) error 事件發(fā)送出來
print("===========")
let subject = BehaviorSubject(value: "默認(rèn)")
//subject.onNext("1")
//subject.onNext("2")
// 前面兩個(gè)<注釋>了,這個(gè)時(shí)候杭抠,發(fā)送默認(rèn)元素
subject.subscribe { (e) in
print("(1) \(e.element ?? "")")
}.disposed(by: disposeBag)
subject.onNext("A")
subject.onNext("B")
subject.subscribe { (e) in
print("(2) \(e.element ?? "")")
}.disposed(by: disposeBag)
subject.onNext("C")
subject.onNext("D")
//輸出:
/**
(1) 默認(rèn)
(1) A
(1) B
(2) B
(1) C
(2) C
(1) D
(2) D
*/
}
ControlProperty
UI相關(guān)的
UITextField
.rx.text.subscribe默認(rèn)會執(zhí)行一次
脸甘,可以跳過.skip(1)或.changed
//Label根據(jù)TextField內(nèi)容改變
//1
self.textField.rx.text.bind(to: self.testLabel.rx.text).disposed(by: disposeBag)
//2
self.textField.rx.text.subscribe { (event: Event<String?>) in
//將UITextField文字改變的內(nèi)容顯示在Label中
self.testLabel.text = event.element!
print(event.element!!)}.disposed(by:disposeBag)
//3
self.textField.rx.text.subscribe(onNext: { (str: String?) in self.testLabel.text = str!}).disposed(by:disposeBag)
self.textField.rx.text.skip(1).subscribe(onNext: { (str: String?) in self.testLabel.text = str!}).disposed(by:disposeBag)
self.textField.rx.text.changed.subscribe(onNext: { (str: String?) in self.testLabel.text = str!}).disposed(by:disposeBag)
//4 監(jiān)聽label內(nèi)容的改變
self.testLabel.rx.observe(String.self, "text").subscribe(onNext: { (str: String?) in print(str!)}).disposed(by:disposeBag)
//5 監(jiān)聽frame的改變(約束不行)
self.testLabel.rx.observe(CGRect.self, "frame").subscribe(onNext: { (rect: CGRect?) in print(rect!.height)}).disposed(by:disposeBag)