- 内存管理老生常谈,首先明确不是所有闭包中使用了
self
,就会造成循环引用,而是一定要产生循环引用链,那么在使用RxSwift
过程中,哪些情况会产生循环引用链?如何打破循环,接下来通过几个Demo
演示如何解决循环引用:
循环引用
- 看一下日常闭包使用:
myClosure = {
self.name = "是否产生了循环引用?"
print(self.name as Any)
}
self.myClosure!()
存在循环引用链:self
->myClosure
->self
接下来打破循环
//=====1.使用weak 修饰 self
myClosure = {[weak self] in
self?.name = "循环引用"
print(self?.name as Any)
}
self.myClosure!()
//=====2.使用unowned
myClosure = {[unowned self] in
self.name = "循环引用"
print(self.name as Any)
}
self.myClosure!()
- 那么在
RxSwift
中如何避免循环引用,看下面demo
self.accountTF.rx.text.orEmpty
.debug()
.subscribe(onNext: { (text) in
self.title = text
})
.disposed(by: disposeBag)
- 很容易找到循环引用链
self
->subscribe
->self
,解决如下:
self.accountTF.rx.text.orEmpty
.debug()
.subscribe(onNext: { [weak self](text) in
self?.title = text
})
.disposed(by: disposeBag)
- 下面的例子循环引用链是:
self
->observable
->create{}
->self
只需引入[weak self]
打破循环
self.observable = Observable<Any>.create { [weak self](anyObserver) -> Disposable in
print(self)
anyObserver.onNext("Hello word")
return Disposables.create()
}
self.observable?.subscribe(onNext: {
print("订阅到1:\($0) --")
})
.disposed(by: self.disposeBag)
- 循环引用链是
self
->observable
->subscribe onNext
->self
,引入[weak self]
,打破循环
self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
anyObserver.onNext("Hello word")
return Disposables.create()
}
// self -> observable -> subscribe onNext -> self
self.observable?.subscribe(onNext: { [weak self] in
print(self)
print("订阅到1:\($0) --")
})
.disposed(by: self.disposeBag)
- 针对下面的这种情况,些微复杂,首先要对
RxSwift
的调用相当了解,否则真的不知道发生了什么,哪里产生了循环引用
Observable<Any>.create { (anyObserver) -> Disposable in
self.observer = anyObserver
anyObserver.onNext("Hello word")
return Disposables.create()
}
.subscribe(onNext: { (item) in
print(self)
print("订阅到:\(item)")
})
.disposed(by: self.disposeBag)
稳住,不要慌,只要对RxSwift
的核心逻辑进行分析,那么这个引用链也就很容易被发现,create
-> self
-> anyObserver
-> observer
-> AnonymousObservableSink.on
-> AnonymousObserver.on
-> onNext?(value)
-> subscribe{}
-> self
,这就是循环应用,只是链比较长,怎么打破就不多说了
跨页面内存管理
在页面间使用RxSwift
进行序列传递,引用计数会不断增加,有几种方法可以保证界面销毁的时候,保证RxSwift
的引用计数不会增多:
- 将
detailVC
创建的序列加入到detailVC.disposeBag
中,保证子页面销毁,序列也跟着销毁:
let detailVC = DetialViewController()
_ = detailVC.publicOB
.subscribe(onNext: { (item) in
print("订阅到 \(item)")
}).disposed(by: detailVC.disposeBag)
self.navigationController?.pushViewController(detailVC, animated: true)
- 使用
takeUntil(detailVC.rx.deallocated)
,让序列跟随detailVC
的生命周期结束而销毁:
let detailVC = DetialViewController()
_ = detailVC.publicOB.takeUntil(detailVC.rx.deallocated)
.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
- 如果是持有子页面的情况,在子页面消失的时候,主动调用序列的
onComplete()
或者onError()
,主动销毁序列:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
mySubject.onCompleted()
}
跳转时页面不作任何改变:
_ = detailVC.publicOB
.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
- 不添加到垃圾袋
let detailVC = DetialViewController()
_ = detailVC.publicOB
.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
以上就是RxSwift
几种常见的内存管理方式。