RxSwift之Subject

RxSwift中的subject懊烤,subject是observable和Observer之間的橋梁梯醒,一個subject既是一個obserable也是一個observe,它既可以發(fā)出事件也可以監(jiān)聽事件
1.publicSubject:訂閱publicSubject時腌紧,只能接收到訂閱他之后發(fā)生的事件茸习,subject.onNext()發(fā)出onNext事件,對應(yīng)的還有onError()和onComplete()事件
2.replaySubject:訂閱replaySubject時壁肋,可以接收到訂閱他之后的事件逮光,但也可以接受訂閱他之前發(fā)出的事件,接受幾個事件取決于bufferSize的大小
3.behaviorSubject:訂閱behaviorSubject,可以接收到訂閱之前的最后一個事件墩划,這個在tableView中用的比較多涕刚,一般就是初始化數(shù)據(jù)顯示空值。

1乙帮,Subjects 基本介紹

(1)Subjects 既是訂閱者杜漠,也是 Observable

  • 說它是訂閱者,是因為它能夠動態(tài)地接收新的值。
  • 說它又是一個 Observable驾茴,是因為當(dāng) Subjects 有了新的值之后盼樟,就會通過 Event 將新值發(fā)出給他的所有訂閱者。

(2)一共有四種 Subjects锈至,分別為:PublishSubject晨缴、BehaviorSubjectReplaySubject峡捡、Variable击碗。他們之間既有各自的特點(diǎn),也有相同之處:

  • 首先他們都是 Observable们拙,他們的訂閱者都能收到他們發(fā)出的新的 Event稍途。
  • 直到 Subject 發(fā)出 .complete 或者 .errorEvent 后,該 Subject 便終結(jié)了砚婆,同時它也就不會再發(fā)出.next事件械拍。
  • 對于那些在 Subject 終結(jié)后再訂閱他的訂閱者,也能收到 subject發(fā)出的一條 .complete.errorevent装盯,告訴這個新的訂閱者它已經(jīng)終結(jié)了坷虑。
  • 他們之間最大的區(qū)別只是在于:當(dāng)一個新的訂閱者剛訂閱它的時候,能不能收到 Subject 以前發(fā)出過的舊 Event埂奈,如果能的話又能收到多少個迄损。

(3)Subject 常用的幾個方法:

  • onNext(:):是 on(.next(:)) 的簡便寫法。該方法相當(dāng)于 subject 接收到一個.next 事件挥转。
  • onError(:):是 on(.error(:)) 的簡便寫法。該方法相當(dāng)于 subject 接收到一個 .error 事件共屈。
  • onCompleted():是 on(.completed)的簡便寫法绑谣。該方法相當(dāng)于 subject 接收到一個 .completed 事件。

2拗引,PublishSubject

(1)基本介紹

  • PublishSubject是最普通的 Subject借宵,它不需要初始值就能創(chuàng)建。
  • PublishSubject 的訂閱者從他們開始訂閱的時間點(diǎn)起矾削,可以收到訂閱后 Subject 發(fā)出的新 Event壤玫,而不會收到他們在訂閱前已發(fā)出的 Event

(2)時序圖

  • 最上面一條是 PublishSubject哼凯。
  • 下面兩條分別表示兩個新的訂閱欲间,它們訂閱的時間點(diǎn)不同,可以發(fā)現(xiàn) PublishSubject 的訂閱者只能收到他們訂閱后的 Event断部。
image

(3)使用樣例

let disposeBag = DisposeBag()

//創(chuàng)建一個PublishSubject
let subject = PublishSubject<String>()

//由于當(dāng)前沒有任何訂閱者猎贴,所以這條信息不會輸出到控制臺
subject.onNext("111")

//第1次訂閱subject
subject.subscribe(onNext: { string in
    print("第1次訂閱:", string)
}, onCompleted:{
    print("第1次訂閱:onCompleted")
}).disposed(by: disposeBag)

//當(dāng)前有1個訂閱,則該信息會輸出到控制臺
subject.onNext("222")

//第2次訂閱subject
subject.subscribe(onNext: { string in
    print("第2次訂閱:", string)
}, onCompleted:{
    print("第2次訂閱:onCompleted")
}).disposed(by: disposeBag)

//當(dāng)前有2個訂閱,則該信息會輸出到控制臺
subject.onNext("333")

//讓subject結(jié)束
subject.onCompleted()

//subject完成后會發(fā)出.next事件了她渴。
subject.onNext("444")

//subject完成后它的所有訂閱(包括結(jié)束后的訂閱)达址,都能收到subject的.completed事件,
subject.subscribe(onNext: { string in
    print("第3次訂閱:", string)
}, onCompleted:{
    print("第3次訂閱:onCompleted")
}).disposed(by: disposeBag)

運(yùn)行結(jié)果如下:

image

3趁耗,BehaviorSubject

(1)基本介紹

  • BehaviorSubject 需要通過一個默認(rèn)初始值來創(chuàng)建沉唠。
  • 當(dāng)一個訂閱者來訂閱它的時候,這個訂閱者會立即收到 BehaviorSubjects 上一個發(fā)出的event苛败。之后就跟正常的情況一樣满葛,它也會接收到 BehaviorSubject 之后發(fā)出的新的 event

(2)時序圖

  • 最上面一條是 BehaviorSubject著拭。
  • 下面兩條分別表示兩個新的訂閱纱扭,它們訂閱的時間點(diǎn)不同,可以發(fā)現(xiàn) BehaviorSubject 的訂閱者一開始就能收到 BehaviorSubjects 之前發(fā)出的一個 Event儡遮。
image

]

(3)使用樣例

let disposeBag = DisposeBag()

//創(chuàng)建一個BehaviorSubject
let subject = BehaviorSubject(value: "111")

//第1次訂閱subject
subject.subscribe { event in
    print("第1次訂閱:", event)
}.disposed(by: disposeBag)

//發(fā)送next事件
subject.onNext("222")

//發(fā)送error事件
subject.onError(NSError(domain: "local", code: 0, userInfo: nil))

//第2次訂閱subject
subject.subscribe { event in
    print("第2次訂閱:", event)
}.disposed(by: disposeBag)

運(yùn)行結(jié)果如下:

image

4乳蛾,ReplaySubject

(1)基本介紹

  • ReplaySubject 在創(chuàng)建時候需要設(shè)置一個 bufferSize,表示它對于它發(fā)送過的 event 的緩存?zhèn)€數(shù)鄙币。
  • 比如一個 ReplaySubjectbufferSize 設(shè)置為 2肃叶,它發(fā)出了 3 個 .nextevent,那么它會將后兩個(最近的兩個)event 給緩存起來十嘿。此時如果有一個 subscriber 訂閱了這個 ReplaySubject因惭,那么這個 subscriber 就會立即收到前面緩存的兩個.nextevent
  • 如果一個 subscriber 訂閱已經(jīng)結(jié)束的 ReplaySubject绩衷,除了會收到緩存的 .nextevent外蹦魔,還會收到那個終結(jié)的 .error 或者 .completeevent

(2)時序圖

  • 最上面一條是 ReplaySubjectbufferSize 設(shè)為為 2)咳燕。
  • 下面兩條分別表示兩個新的訂閱勿决,它們訂閱的時間點(diǎn)不同≌忻ぃ可以發(fā)現(xiàn) ReplaySubject的訂閱者一開始就能收到ReplaySubject 之前發(fā)出的兩個 Event(如果有的話)低缩。
image

(3)使用樣例

let disposeBag = DisposeBag()

//創(chuàng)建一個bufferSize為2的ReplaySubject
let subject = ReplaySubject<String>.create(bufferSize: 2)

//連續(xù)發(fā)送3個next事件
subject.onNext("111")
subject.onNext("222")
subject.onNext("333")

//第1次訂閱subject
subject.subscribe { event in
    print("第1次訂閱:", event)
}.disposed(by: disposeBag)

//再發(fā)送1個next事件
subject.onNext("444")

//第2次訂閱subject
subject.subscribe { event in
    print("第2次訂閱:", event)
}.disposed(by: disposeBag)

//讓subject結(jié)束
subject.onCompleted()

//第3次訂閱subject
subject.subscribe { event in
    print("第3次訂閱:", event)
}.disposed(by: disposeBag)

運(yùn)行結(jié)果如下:

image

5,Variable

(1)基本介紹

  • Variable 其實就是對 BehaviorSubject 的封裝曹货,所以它也必須要通過一個默認(rèn)的初始值進(jìn)行創(chuàng)建咆繁。
  • Variable 具有 BehaviorSubject 的功能,能夠向它的訂閱者發(fā)出上一個 event 以及之后新創(chuàng)建的 event顶籽。
  • 不同的是玩般,Variable 還會把當(dāng)前發(fā)出的值保存為自己的狀態(tài)。同時它會在銷毀時自動發(fā)送 .completeevent礼饱,不需要也不能手動給 Variables 發(fā)送 completed或者 error 事件來結(jié)束它壤短。
  • 簡單地說就是 Variable 有一個 value 屬性设拟,我們改變這個 value 屬性的值就相當(dāng)于調(diào)用一般 SubjectsonNext() 方法,而這個最新的 onNext() 的值就被保存在 value 屬性里了久脯,直到我們再次修改它纳胧。

注意
Variables 本身沒有 subscribe() 方法,但是所有 Subjects 都有一個 asObservable() 方法帘撰。我們可以使用這個方法返回這個 VariableObservable 類型跑慕,拿到這個 Observable 類型我們就能訂閱它了。

(2)使用樣例

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let disposeBag = DisposeBag()

        //創(chuàng)建一個初始值為111的Variable
        let variable = Variable("111")

        //修改value值
        variable.value = "222"

        //第1次訂閱
        variable.asObservable().subscribe {
            print("第1次訂閱:", $0)
        }.disposed(by: disposeBag)

        //修改value值
        variable.value = "333"

        //第2次訂閱
        variable.asObservable().subscribe {
            print("第2次訂閱:", $0)
        }.disposed(by: disposeBag)

        //修改value值
        variable.value = "444"
    }
}

運(yùn)行結(jié)果如下:

注意:由于 Variable對象在viewDidLoad() 方法內(nèi)初始化摧找,所以它的生命周期就被限制在該方法內(nèi)核行。當(dāng)這個方法執(zhí)行完畢后,這個 Variable 對象就會被銷毀蹬耘,同時它也就自動地向它的所有訂閱者發(fā)出.completed 事件

image

RxSwift使用詳解系列

作者:八級大狂風(fēng)AM
鏈接:http://www.reibang.com/p/def6965b0475

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芝雪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子综苔,更是在濱河造成了極大的恐慌惩系,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件如筛,死亡現(xiàn)場離奇詭異堡牡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)杨刨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門晤柄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人妖胀,你說我怎么就攤上這事芥颈。” “怎么了赚抡?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵爬坑,是天一觀的道長。 經(jīng)常有香客問我怕品,道長妇垢,這世上最難降的妖魔是什么巾遭? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任肉康,我火速辦了婚禮,結(jié)果婚禮上灼舍,老公的妹妹穿的比我還像新娘吼和。我一直安慰自己,他們只是感情好骑素,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布炫乓。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪末捣。 梳的紋絲不亂的頭發(fā)上侠姑,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機(jī)與錄音箩做,去河邊找鬼莽红。 笑死,一個胖子當(dāng)著我的面吹牛邦邦,可吹牛的內(nèi)容都是我干的安吁。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼燃辖,長吁一口氣:“原來是場噩夢啊……” “哼鬼店!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起黔龟,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤妇智,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捌锭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俘陷,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年观谦,在試婚紗的時候發(fā)現(xiàn)自己被綠了拉盾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡豁状,死狀恐怖捉偏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情泻红,我是刑警寧澤夭禽,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站谊路,受9級特大地震影響讹躯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缠劝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一潮梯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惨恭,春花似錦秉馏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽免都。三九已至,卻和暖如春帆竹,著一層夾襖步出監(jiān)牢的瞬間绕娘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工栽连, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留业舍,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓升酣,卻偏偏與公主長得像舷暮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子噩茄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容