RXSwift常見(jiàn)問(wèn)題和注意事項(xiàng)

RxSwift 講述到此, 基本使用和核心邏輯都已經(jīng)有所介紹. 那么本文就實(shí)際開(kāi)發(fā)中,使用 RxSwift 時(shí)經(jīng)常會(huì)遇到的問(wèn)題列舉講述.

RxSwift中何時(shí)需要使用 [weak self] / [unowned self]

這個(gè)內(nèi)存管理的問(wèn)題, 想深度了解的同學(xué)可以先閱讀一下
RXSwift內(nèi)存管理探索
RXSwift之Dispose銷(xiāo)毀者解析

首先需要搞清楚的是:
當(dāng)閉包里使用 self 到底會(huì)不會(huì)產(chǎn)生循環(huán)引用.

想解決這個(gè)問(wèn)題, 建議按部就班 順著引用鏈查找,直到閉包執(zhí)行完畢. 如果頁(yè)面/ 類(lèi)中閉包較少, 可以通過(guò)查看 deinit 方法走不走來(lái)查找. 當(dāng)然,在 RxSwift 的世界中, 往往走了 deinit 也不一定完全安全. 可以通過(guò) Rx 提供的引用計(jì)數(shù)幫助查找. (比如對(duì)象銷(xiāo)毀了,但是訂閱沒(méi)有銷(xiāo)毀的情況)

舉例:

var myClosure: (() -> Void)?  //vc的一個(gè)屬性

myClosure = {
    print("\(self.name)")
}
        
myClosure?()

如果 myClosure 是寫(xiě)在外部的 VC 的一個(gè)屬性. 因此 self->myClosure->self 則會(huì)造成循環(huán)引用.
反之 myClosure 只是一個(gè)方法中的臨時(shí)變量.那么就完全可以在該閉包中使用 self .

另外需要注意的是, Rxswift 中的 訂閱 subscribe 本身就是循環(huán)引用, 因此,在 subscribe 中有出現(xiàn) self 時(shí),一定要使用 [weak self]

例子:

Observable<Any>.create { (anyObserver) -> Disposable in
        anyObserver.onNext("Hello word")
        return Disposables.create()
    }
    .subscribe(onNext: { (item) in
        print(self)
        print("訂閱到:\(item)")
    })

以上案例中 subscribe 閉包持有 self. 但是從外部看并沒(méi)有構(gòu)成循環(huán)引用. 其實(shí) subscribe 時(shí),產(chǎn)生的中間類(lèi) sink 本身就是循環(huán)引用的. 當(dāng)這個(gè) sink 不釋放,那么它間接持有的 self 就不會(huì)釋放.
就算在最后加上 .disposed(by: self.disposeBag) , 那么 self 的確可以釋放, 但是查看引用計(jì)數(shù)會(huì)發(fā)現(xiàn), 還是在不斷攀升


所以我們需要使用 [weak self].

完整寫(xiě)法:

    Observable<Any>.create { (anyObserver) -> Disposable in
        self.observer = anyObserver
        anyObserver.onNext("Hello word")
        return Disposables.create()
    }
    .subscribe(onNext: {[weak self] (item) in
        print(self)
        print("訂閱到:\(item)")
    })
    .disposed(by: self.disposeBag)

總結(jié)一句話就是 當(dāng)訂閱閉包使用了 self, 一定要配合 disposeBag[weak self].

那么什么時(shí)候使用 [weak self] , 什么時(shí)候使用 [unowned self] 呢?
記住以下幾點(diǎn):

  • unowned訪問(wèn)已經(jīng)釋放的對(duì)象時(shí)會(huì)崩潰
    weak 會(huì)打印 nil ,不會(huì)崩潰.
  • 因此. 在確認(rèn)閉包執(zhí)行完成之后視圖控制器/對(duì)象才會(huì)被釋放時(shí)使用,其他情況使用 weak.
  • 除非自己需要把異常拋出,容易查找, 使用 unowned.

RxSwift中DisposeBag / Dispose該如何寫(xiě)?

這也是一個(gè)內(nèi)存管理的問(wèn)題.
回答:

  • 一般情況我們會(huì)在一個(gè)視圖控制器中定義一個(gè) DisposeBag 的屬性. 那么這個(gè)垃圾袋就會(huì)隨著 vc 的生命周期調(diào)用其管理對(duì)象的釋放.
  • 當(dāng)需要手動(dòng)釋放時(shí), 手動(dòng)將垃圾袋置為 nil. 那么該垃圾袋管理的對(duì)象都會(huì)被釋放.

Dispose, deinit 方法的調(diào)用時(shí)機(jī)必須要掌握清楚. 不太熟悉的同學(xué)可以閱讀一下
RXSwift之Dispose銷(xiāo)毀者解析

值得注意的是,當(dāng)訂閱事件為一個(gè)異步任務(wù)時(shí), 需要時(shí)刻注意訂閱者在執(zhí)行任務(wù)時(shí)是否會(huì)被釋放掉.

舉個(gè)例子, 筆者之前有一個(gè)寫(xiě)法, 下載一張圖片, 由于需要用緩存 所以我創(chuàng)建了一個(gè)臨時(shí) ImageView 來(lái)使用 SDWebImage 加載這張圖片. 然后在其 complete 回調(diào)中獲取這張圖片用于其他處理.

可是筆者卻發(fā)現(xiàn)下載完成回調(diào)確死活不執(zhí)行. 仔細(xì)研究才發(fā)現(xiàn):
由于這個(gè)臨時(shí) ImageView 在方法執(zhí)行完就會(huì)釋放. 其回調(diào)當(dāng)然不走了.
因此 , 筆者將此 ImageView 改為屬性解決了這個(gè)問(wèn)題.

RxSwift中使用 KVO 的問(wèn)題

RxSwift對(duì) KVO 的調(diào)用主要有兩種方式:

  • rx.observe:更加高效,因?yàn)樗且粋€(gè)KVO機(jī)制的簡(jiǎn)單封裝斩郎。

  • rx.observeWeakly :執(zhí)行效率要低一些脑融,因?yàn)樗幚韺?duì)象的釋放防止弱引用(對(duì)象的dealloc關(guān)系)。

應(yīng)用場(chǎng)景:

  • 可以在使用 rx.observe 的地方都可以使用 rx.observeWeakly缩宜。
  • 使用 rx.observe 時(shí)路徑只能包括 strong 屬性肘迎,否則就會(huì)有系統(tǒng)崩潰的風(fēng)險(xiǎn)。而 rx.observeWeakly 可以用在weak屬性上。

RxSwift中使用 Subject / Variable 的問(wèn)題

由于 Subject / Variable 既具備序列 也具備觀察者的特性, 其在實(shí)際開(kāi)發(fā)中經(jīng)常被廣泛使用. 但也正因此, 造成風(fēng)險(xiǎn),代碼可讀性差,等問(wèn)題.
因此, 一般在使用 Subject / Variable 要將其暴露給外部使用時(shí),我們經(jīng)常會(huì)單獨(dú)暴露其一個(gè)方面給外界.

比如
我自己管理發(fā)送 ,只暴露給外部訂閱的權(quán)利.

fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
   return mySubject.asObservable()
}

我自己管理訂閱處理 ,只暴露給外部發(fā)送的權(quán)利.

fileprivate var mySubject = PublishSubject<Any>()
var ober: AnyObserver<Any>{
   return mySubject.asObserver()
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膜宋,一起剝皮案震驚了整個(gè)濱河市窿侈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秋茫,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乃秀,死亡現(xiàn)場(chǎng)離奇詭異肛著,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)跺讯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)枢贿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人刀脏,你說(shuō)我怎么就攤上這事局荚。” “怎么了愈污?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵耀态,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我暂雹,道長(zhǎng)首装,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任杭跪,我火速辦了婚禮仙逻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涧尿。我一直安慰自己系奉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布姑廉。 她就那樣靜靜地躺著缺亮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪庄蹋。 梳的紋絲不亂的頭發(fā)上瞬内,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音限书,去河邊找鬼虫蝶。 笑死,一個(gè)胖子當(dāng)著我的面吹牛倦西,可吹牛的內(nèi)容都是我干的能真。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粉铐!你這毒婦竟也來(lái)了疼约?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蝙泼,失蹤者是張志新(化名)和其女友劉穎程剥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體汤踏,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡织鲸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了溪胶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搂擦。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哗脖,靈堂內(nèi)的尸體忽然破棺而出瀑踢,到底是詐尸還是另有隱情,我是刑警寧澤才避,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布橱夭,位于F島的核電站,受9級(jí)特大地震影響工扎,放射性物質(zhì)發(fā)生泄漏徘钥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一肢娘、第九天 我趴在偏房一處隱蔽的房頂上張望呈础。 院中可真熱鬧,春花似錦橱健、人聲如沸而钞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)臼节。三九已至,卻和暖如春珊皿,著一層夾襖步出監(jiān)牢的瞬間网缝,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工蟋定, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留粉臊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓驶兜,卻偏偏與公主長(zhǎng)得像扼仲,于是被迫代替她去往敵國(guó)和親远寸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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