Subjects
創(chuàng)建 Observable 序列之后, 要預(yù)先將要發(fā)出的數(shù)據(jù)準(zhǔn)備好, 等到有人訂閱時(shí), 再將數(shù)據(jù)通過 Event 發(fā)出去.
我們希望 Observable 序列能在運(yùn)行時(shí)動(dòng)態(tài)的 獲得 或者說 產(chǎn)生 一個(gè)新數(shù)據(jù), 再通過 Event 發(fā)送出去. 比如: 訂閱一個(gè)輸入框的輸入內(nèi)容, 當(dāng)用戶每輸入一個(gè)字后, 這個(gè)輸入框關(guān)聯(lián)的 Observable 就會(huì)發(fā)出一個(gè)帶有輸入內(nèi)容的 Event, 通知給所有的訂閱者. 這個(gè)就可以使用 Subjects 來實(shí)現(xiàn).
Subjects 基本介紹
(1) Subjects 它是訂閱者, 也是 Obervable :
- 它是訂閱者, 因?yàn)樗軌騽?dòng)態(tài)的接收新的值
- 它是一個(gè)
Observable, 是因?yàn)楫?dāng)Subjects有了新的值之后, 就會(huì)通過Event將新值發(fā)出給他的所有訂閱者.
(2) 一共有四種 Subjects, 分別是 PublishSubject、BehaviorSubject、ReplaySubject 、 Variable(已廢棄) 和 BehaviorRelay(Variable替代品).
- 它們都是
Observable, 它們的訂閱者都能收到它們發(fā)出的Event - 直到
Subject發(fā)出.complete或者.error的Event之后, 該Subject才會(huì)終結(jié), 不再發(fā)出.next事件. - 對(duì)于那些在
Subject終結(jié)后再訂閱的訂閱者, 也能收到一條.complete或者.error的Event, 告訴這個(gè)新訂閱者, 該Subject已經(jīng)終結(jié) - 它們的區(qū)別在于 : 當(dāng)一個(gè)新的訂閱者剛訂閱它的時(shí)候,能不能收到
Subject以前發(fā)出的舊Event, 如果能,又可以收到多少個(gè)Event.
(3) Subject 的常用方法
- onNext() :
on(.next):的簡(jiǎn)寫, 該方法相當(dāng)于subject接收到一個(gè).next事件. - onError() :
on(.error):的簡(jiǎn)寫, 該方法相當(dāng)于subject接收到一個(gè).error事件. - onCompleted() :
on(.completed):的簡(jiǎn)寫, 該方法相當(dāng)于subjet接收到一個(gè).completed事件
PublishSubject
(1) 基本介紹
-
PublishSubject是最普通的Subjet, 它不需要初始值就能創(chuàng)建. -
PublishSubject的訂閱者從開始訂閱的時(shí)間點(diǎn)起,可以收到訂閱Subject發(fā)出的新的Event, 而不會(huì)收到他們?cè)谟嗛喦耙寻l(fā)出的Event.

PublishSubject.png
(2)案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
//創(chuàng)建一個(gè)PublishSubject
let subject = PublishSubject<String>()
subject.onNext("11") //此時(shí)沒有訂閱者,不會(huì)輸出
//首次訂閱
subject.subscribe(onNext: { str in
print("第一次訂閱: ", str)
}, onCompleted: {
print("第一次訂閱 : onCompleted")
}).disposed(by: disposeBag)
//有訂閱者,會(huì)輸出
subject.onNext("22")
subject.subscribe(onNext: { (str) in
print("第二次訂閱: ", str)
}, onCompleted: {
print("第二次訂閱 : onCompleted")
}).disposed(by: disposeBag)
subject.onNext("33")//兩個(gè)訂閱者,輸出兩遍
subject.onCompleted()//結(jié)束兩個(gè)訂閱者,打印兩遍
subject.onNext("44")//再次發(fā)送event,不會(huì)打印
//再有新的訂閱者,會(huì)收到onCompleted消息,通知新的訂閱者,該Subject已經(jīng)終結(jié)
subject.subscribe(onNext: { (str) in
print("第三次訂閱: ", str)
}, onCompleted: {
print("第三次訂閱 : onCompleted")
}).disposed(by: disposeBag)
}
//輸出結(jié)果
第一次訂閱: 22
第一次訂閱: 33
第二次訂閱: 33
第一次訂閱 : onCompleted
第二次訂閱 : onCompleted
第三次訂閱 : onCompleted
BehaviorSubject
(1) 基本介紹
-
BehaviorSubject需要通過一個(gè)默認(rèn)初始值來創(chuàng)建 - 當(dāng)一個(gè)訂閱者來訂閱它的時(shí)候, 這個(gè)訂閱者會(huì)立即收到
BehaviorSubject上一個(gè)發(fā)出的event, 之后就是正常流程
BehaviorSubject.png
(2) 使用示例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "111")
//第一次訂閱subject(先發(fā)出上一個(gè)event)
subject.subscribe { (event) in
print("第一次訂閱: ", event)
}.disposed(by: disposeBag)
//發(fā)送next事件
subject.onNext("222")
subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
//重復(fù)結(jié)束event,輸出error
subject.subscribe { (event) in
print("第二次訂閱: ",event)
}.disposed(by: disposeBag)
}
//輸出結(jié)果
第一次訂閱: next(111)
第一次訂閱: next(222)
第一次訂閱: error(Error Domain=local Code=0 "(null)")
第二次訂閱: error(Error Domain=local Code=0 "(null)")
ReplaySubject
(1) 基本介紹
-
ReplaySubject在創(chuàng)建的時(shí)候需要設(shè)置一個(gè)bufferSize, 表示它發(fā)送過的event緩存?zhèn)€數(shù). 比如 : 一個(gè)ReplaySubject的bufferSize設(shè)置為2, 它發(fā)出了三個(gè).next的event, 那么這個(gè)subscriber就會(huì)立即收到前面緩存的兩個(gè).next的event
(2) 時(shí)序圖
-
ReplaySubject的bufferSize為2 - 下面兩條訂閱, 訂閱時(shí)間點(diǎn)不同.
ReplaySubject的訂閱者一開始就能受到ReplaySubject之前發(fā)出的兩個(gè)Event(如果有的話).
ReplaySubject.png
(3)案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 2);
//連續(xù)發(fā)出三個(gè)event
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
//第一次訂閱
subject.subscribe { (event) in
print("第一次訂閱", event)
}.disposed(by: disposeBag)
subject.onNext("4")
subject.subscribe { (event) in
print("第二次訂閱", event)
}
subject.onCompleted();
subject.subscribe { (event) in
print("第三次訂閱", event)
}.disposed(by: disposeBag)
}
//輸出結(jié)果
第一次訂閱 next(2)
第一次訂閱 next(3)
第一次訂閱 next(4)
第二次訂閱 next(3)
第二次訂閱 next(4)
第一次訂閱 completed
第二次訂閱 completed
第三次訂閱 next(3)
第三次訂閱 next(4)
第三次訂閱 completed
BehaviorRelay
(1) 基本介紹
-
BehaviorRelay是作為Variable的替代者出現(xiàn)的. 它的本質(zhì)其實(shí)也是對(duì)BehaviorRelay的封裝, 所以它也必須要通過一個(gè)默認(rèn)的初始值進(jìn)行創(chuàng)建 -
BehaviorReplay具有BehaviorSubject的功能, 能夠向它的訂閱者發(fā)出上一個(gè)event以及之后新創(chuàng)建的event - 與
BehaviorSubject不同的是,不需要也不能手動(dòng)給BehaviorReply發(fā)送completed或者error事件來結(jié)束它(BehaviorRelay會(huì)在銷毀時(shí)自動(dòng)發(fā)送.complete的 event)。 -
BehaviorReplay有一個(gè)value屬性, 我們通過這個(gè)屬性可以獲取最新值. 而通過它的accept()方法可以對(duì)值進(jìn)行修改.
(2) 案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = BehaviorRelay<String>(value: "111");
// 修改value值
subject.accept("222");
//第一次訂閱
subject.subscribe { (event) in
print("第一次訂閱: ", event)
}.disposed(by: disposeBag)
//修改value值
subject.accept("333")
subject.subscribe { (event) in
print("第二次訂閱 :", event)
}.disposed(by: disposeBag)
subject.accept("444")
}
//輸出結(jié)果
第一次訂閱: next(222)
第一次訂閱: next(333)
第二次訂閱 : next(333)
第一次訂閱: next(444)
第二次訂閱 : next(444)

