在我們所遇到的事物中,有一部分非常特別。它們既是可監聽序列也是觀察者。
例如:textField
的當前文本。它可以看成是由用戶輸入,而產生的一個文本序列。也可以是由外部文本序列,來控制當前顯示內容的觀察者:
// 作為可監聽序列
let observable = textField.rx.text
observable.subscribe(onNext: { text in show(text: text) })
// 作為觀察者
let observer = textField.rx.text
let text: Observable<String?> = ...
text.bind(to: observer)
有許多 UI 控件都存在這種特性,例如:switch
的開關狀態,segmentedControl
的選中索引號,datePicker
的選中日期等等。
AsyncSubject
AsyncSubject 將在源 Observable
產生完成事件后,發出最后一個元素(僅僅只有最后一個元素),如果源 Observable
沒有發出任何元素,只有一個完成事件。那 AsyncSubject 也只有一個完成事件。
它會對隨后的觀察者發出最終元素。如果源 Observable
因為產生了一個 error
事件而中止, AsyncSubject 就不會發出任何元素,而是將這個 error
事件發送出來。
演示
let disposeBag = DisposeBag()
let subject = AsyncSubject<String>()
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("??")
subject.onNext("??")
subject.onNext("??")
subject.onCompleted()
輸出結果:
Subscription: 1 Event: next(??)
Subscription: 1 Event: completed
PublishSubject
PublishSubject 將對觀察者發送訂閱后產生的元素,而在訂閱前發出的元素將不會發送給觀察者。如果你希望觀察者接收到所有的元素,你可以通過使用 Observable
的 create
方法來創建 Observable
,或者使用 ReplaySubject。
如果源 Observable
因為產生了一個 error
事件而中止, PublishSubject 就不會發出任何元素,而是將這個 error
事件發送出來。
演示
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("??")
subject.onNext("??")
subject
.subscribe { print("Subscription: 2 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("???")
subject.onNext("???")
輸出結果:
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
ReplaySubject
ReplaySubject 將對觀察者發送全部的元素,無論觀察者是何時進行訂閱的。
這里存在多個版本的 ReplaySubject,有的只會將最新的 n 個元素發送給觀察者,有的只會將限制時間段內最新的元素發送給觀察者。
如果把 ReplaySubject 當作觀察者來使用,注意不要在多個線程調用 onNext
, onError
或 onCompleted
。這樣會導致無序調用,將造成意想不到的結果。
演示
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("??")
subject.onNext("??")
subject
.subscribe { print("Subscription: 2 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("???")
subject.onNext("???")
輸出結果:
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
BehaviorSubject
當觀察者對 BehaviorSubject 進行訂閱時,它會將源 Observable
中最新的元素發送出來(如果不存在最新的元素,就發出默認元素)。然后將隨后產生的元素發送出來。
如果源 Observable
因為產生了一個 error
事件而中止, BehaviorSubject 就不會發出任何元素,而是將這個 error
事件發送出來。
演示
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "??")
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("??")
subject.onNext("??")
subject
.subscribe { print("Subscription: 2 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("???")
subject.onNext("???")
subject
.subscribe { print("Subscription: 3 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("??")
subject.onNext("??")
輸出結果:
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 3 Event: next(???)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 3 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 3 Event: next(??)
ControlProperty
ControlProperty 專門用于描述 UI 控件屬性的,它具有以下特征:
- 不會產生
error
事件 - 一定在
MainScheduler
訂閱(主線程訂閱) - 一定在
MainScheduler
監聽(主線程監聽) 共享附加作用
青山不改,綠水長流,后會有期,感謝大家支持!