Subjects 介绍
Subjects
是订阅者,也是Observable
:
订阅者:它能动态的接收新的值。
Observable: 当Subjects有了新值后会通过Event将新值发出给他的所有订阅者。
Subjects
有四种:PublishSubject、BehaviorSubject、ReplaySubject、Variable
相同点
都是Observable,他们的订阅者都能接收他们发出的新的Event
直到 Subject 发出 .complete 或者 .error 的 Event 后,该 Subject 便终结了,同时它也就不会再发出.next事件。
在Subject 终结后再订阅他的订阅者,也能收到 subject发出的一条.complete 或.error的event,
不同点
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
将发送订阅后产生的元素,而之前元素将不会发送给观察者
结束
之后添加的订阅能收到 completed
结束
后发的都收不到
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 产生完成事件后,发出最后一个元素(仅仅只有最后一个元素),
如果源 Observable 没有发出任何元素,只有一个完成事件
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") //执行
asyncSubject.onCompleted()//执行
//输出:
//C
//xx
}
AsyncSubject
如果源 Observable 因为产生了一个 error 事件而中止,
就不会发出任何元素,而是将这个 error 事件发送出来
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) //执行
asyncSubject.onCompleted()
//输出:
//error(A)
}
ReplaySubject
将发送全部的元素,无论是何时进行订阅的
结束后订阅
,不仅会收到最后的n个 event 还有 Completed
func testReplaySubject() {
//多个版本的 ReplaySubject,有的只会将最新的 n 个元素发送给观察者,有的只会将 限制时间段内 最新的元素发送给观察者
//如果把 ReplaySubject 当作观察者来使用,注意不要在多个线程调用 onNext, onError 或 onCompleted。这样会导致无序调用,将造成意想不到的结果
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("-------")
/// 不仅会收到最后的两个 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
它会将最新的元素 发送出来(如果不存在最新的,就发出默认元素)。
需要一个默认值初始化
当一个订阅者
订阅之后会立马收到上一个Event,之后就是正常情况发一个收一个
func testBehaviorSubject() {
//如果源 Observable 因为产生了一个 error 事件而中止, BehaviorSubject 就不会发出任何元素,而是将这个 error 事件发送出来
print("===========")
let subject = BehaviorSubject(value: "默认")
//subject.onNext("1")
//subject.onNext("2")
// 前面两个<注释>了,这个时候,发送默认元素
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) 默认
(1) A
(1) B
(2) B
(1) C
(2) C
(1) D
(2) D
*/
}
ControlProperty
UI相关的
UITextField
.rx.text.subscribe默认会执行一次
,可以跳过.skip(1)或.changed
//Label根据TextField内容改变
//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文字改变的内容显示在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 监听label内容的改变
self.testLabel.rx.observe(String.self, "text").subscribe(onNext: { (str: String?) in print(str!)}).disposed(by:disposeBag)
//5 监听frame的改变(约束不行)
self.testLabel.rx.observe(CGRect.self, "frame").subscribe(onNext: { (rect: CGRect?) in print(rect!.height)}).disposed(by:disposeBag)
网友评论