RXSwift常见问题和注意事项

RxSwift 讲述到此, 基本使用和核心逻辑都已经有所介绍. 那么本文就实际开发中,使用 RxSwift 时经常会遇到的问题列举讲述.

RxSwift中何时需要使用 [weak self] / [unowned self]

这个内存管理的问题, 想深度了解的同学可以先阅读一下
RXSwift内存管理探索
RXSwift之Dispose销毁者解析

首先需要搞清楚的是:
当闭包里使用 self 到底会不会产生循环引用.

想解决这个问题, 建议按部就班 顺着引用链查找,直到闭包执行完毕. 如果页面/ 类中闭包较少, 可以通过查看 deinit 方法走不走来查找. 当然,在 RxSwift 的世界中, 往往走了 deinit 也不一定完全安全. 可以通过 Rx 提供的引用计数帮助查找. (比如对象销毁了,但是订阅没有销毁的情况)

举例:

var myClosure: (() -> Void)?  //vc的一个属性

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

如果 myClosure 是写在外部的 VC 的一个属性. 因此 self->myClosure->self 则会造成循环引用.
反之 myClosure 只是一个方法中的临时变量.那么就完全可以在该闭包中使用 self .

另外需要注意的是, Rxswift 中的 订阅 subscribe 本身就是循环引用, 因此,在 subscribe 中有出现 self 时,一定要使用 [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. 但是从外部看并没有构成循环引用. 其实 subscribe 时,产生的中间类 sink 本身就是循环引用的. 当这个 sink 不释放,那么它间接持有的 self 就不会释放.
就算在最后加上 .disposed(by: self.disposeBag) , 那么 self 的确可以释放, 但是查看引用计数会发现, 还是在不断攀升


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

完整写法:

    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)

总结一句话就是 当订阅闭包使用了 self, 一定要配合 disposeBag[weak self].

那么什么时候使用 [weak self] , 什么时候使用 [unowned self] 呢?
记住以下几点:

  • unowned访问已经释放的对象时会崩溃
    weak 会打印 nil ,不会崩溃.
  • 因此. 在确认闭包执行完成之后视图控制器/对象才会被释放时使用,其他情况使用 weak.
  • 除非自己需要把异常抛出,容易查找, 使用 unowned.

RxSwift中DisposeBag / Dispose该如何写?

这也是一个内存管理的问题.
回答:

  • 一般情况我们会在一个视图控制器中定义一个 DisposeBag 的属性. 那么这个垃圾袋就会随着 vc 的生命周期调用其管理对象的释放.
  • 当需要手动释放时, 手动将垃圾袋置为 nil. 那么该垃圾袋管理的对象都会被释放.

Dispose, deinit 方法的调用时机必须要掌握清楚. 不太熟悉的同学可以阅读一下
RXSwift之Dispose销毁者解析

值得注意的是,当订阅事件为一个异步任务时, 需要时刻注意订阅者在执行任务时是否会被释放掉.

举个例子, 笔者之前有一个写法, 下载一张图片, 由于需要用缓存 所以我创建了一个临时 ImageView 来使用 SDWebImage 加载这张图片. 然后在其 complete 回调中获取这张图片用于其他处理.

可是笔者却发现下载完成回调确死活不执行. 仔细研究才发现:
由于这个临时 ImageView 在方法执行完就会释放. 其回调当然不走了.
因此 , 笔者将此 ImageView 改为属性解决了这个问题.

RxSwift中使用 KVO 的问题

RxSwift对 KVO 的调用主要有两种方式:

  • rx.observe:更加高效,因为它是一个KVO机制的简单封装。

  • rx.observeWeakly :执行效率要低一些,因为它要处理对象的释放防止弱引用(对象的dealloc关系)。

应用场景:

  • 可以在使用 rx.observe 的地方都可以使用 rx.observeWeakly
  • 使用 rx.observe 时路径只能包括 strong 属性,否则就会有系统崩溃的风险。而 rx.observeWeakly 可以用在weak属性上。

RxSwift中使用 Subject / Variable 的问题

由于 Subject / Variable 既具备序列 也具备观察者的特性, 其在实际开发中经常被广泛使用. 但也正因此, 造成风险,代码可读性差,等问题.
因此, 一般在使用 Subject / Variable 要将其暴露给外部使用时,我们经常会单独暴露其一个方面给外界.

比如
我自己管理发送 ,只暴露给外部订阅的权利.

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

我自己管理订阅处理 ,只暴露给外部发送的权利.

fileprivate var mySubject = PublishSubject<Any>()
var ober: AnyObserver<Any>{
   return mySubject.asObserver()
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容