You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxSwift中Driver为何不会产生循环引用?

RxSwift中Driver不会产生循环引用的原因解析

你的两段代码的差异本质在于是否形成强引用闭环,而非Driver本身存在特殊的弱引用处理逻辑,以下是具体分析:

第二段代码内存泄漏的原因

这段代码中,你在subscribe的闭包内通过[self]显式强引用了ViewController:

publishRelay
    .subscribe(onNext: { [self] _ in
        self.publishRelay2.onNext("")
    })
    .disposed(by: disposeBag)

形成的强引用链为:

  • ViewController 强持有 publishRelay 和 disposeBag
  • publishRelay 强持有订阅闭包(RxSwift的订阅逻辑中,序列会持有订阅回调闭包)
  • 闭包通过[self]强持有 ViewController

这个闭环会导致ViewController的引用计数永远无法降为0,disposeBag无法被释放、订阅也不会销毁,最终造成内存泄漏,ViewController无法执行deinit。

第一段代码能正常释放的原因

再看使用drive的代码:

publishRelay
    .asDriver(onErrorJustReturn: "")
    .drive(self.publishRelay2)
    .disposed(by: disposeBag)

这里的引用关系是:

  • ViewController 强持有 publishRelay、publishRelay2 和 disposeBag
  • publishRelay(经asDriver转换后的序列)通过drive订阅,强持有观察者publishRelay2
  • publishRelay2 是ViewController的属性,但它本身不会反向持有ViewController(Relay仅作为事件容器,不持有其所有者)

此时并未形成闭环:当ViewController的外部引用被移除后,其引用计数降为0,disposeBag会被释放,进而销毁所有绑定的订阅,publishRelay对publishRelay2的强引用被断开,整个引用链被打破,ViewController可以正常执行deinit。

为什么查看drive源码看不到弱引用?

因为完全不需要。drive的核心是将序列绑定到观察者,而非通过闭包捕获self。你传递的self.publishRelay2只是把观察者对象传给序列,观察者本身不持有ViewController,自然不会产生循环引用,也就不需要额外的弱引用处理。

如果把第二段代码改成弱引用捕获self,同样可以避免内存泄漏:

publishRelay
    .subscribe(onNext: { [weak self] _ in
        guard let self = self else { return }
        self.publishRelay2.onNext("")
    })
    .disposed(by: disposeBag)

内容的提问来源于stack exchange,提问作者Choijun0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:13:12