一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
- 本文主要介绍下RxSwift中的循环引用问题。
1. 闭包的循环引用
再讨论RxSwift中的内存管理,我们先回顾下Swift中闭包的循环引用问题
var myClousre:(()->())?
var name: String?
override func viewDidLoad() {
super.viewDidLoad()
print("来了")
self.myClousre = {
self.name = "jack"
}
// Do any additional setup after loading the view.
}
我们push到子页面,定义一个闭包。在闭包中设置当前控制器的属性name。
捕获了对象,并修改了控制器的name的值但是没有执行deInit,此时self是全局变量没有释放.
此时就是self->myClousre->self,造成了循环引用。
- 解决 我们可以使用若引用或者无主引用打破循环
弱引用weak
无主引用unowned
无主引用unowned表示的你明确当前闭包和持有者的生命周期是一致的,比如我们当前的控制器和闭包是相互统一的生命周期。weak修饰的话则是不确定它们的生命周期是否一致,所以会有一个可选值?闭包修饰持有者。
关于Swift中内存管理可以看下之前我的文章swfit进阶-06-内存管理
2. RxSwift中的循环引用
我们使用RxSwift再序列中的闭包调用自身属性
var name: String?
let disposeBag = DisposeBag()
var ob: Observable<Int>?
override func viewDidLoad() {
super.viewDidLoad()
print("来了")
print(RxSwift.Resources.total)
self.ob = Observable<Int>.create({ observer in
self.name = "jack"
return Disposables.create()
})
self.ob?.subscribe(onNext: { _ in
print(self.name! as Any)
}).disposed(by: disposeBag)
print(RxSwift.Resources.total)
其中RxSwift.Resources.total是
计算内部Rx资源分配(可观察对象、观察对象、一次性物品等)。这提供了一种在开发期间检测泄漏的简单方法。
打印结果:
我们使用弱引用和无主引用的时候打破循环
对于我们RxSwift同样具有循环引用问题,也需要进行弱引用或无主引用打破循环。