摘录:
RxSwift源码分析(20)——内存管理
RxSwift源码分析(2)——核心逻辑
RxSwift源码分析(14)——Disposable销毁者
1:未持有,无订阅,不循环
2:未持有,持有,最好weak
3、 调用 onCompleted ,查看源码会发现当发送 .complete 事件时,
rx 内部会自动调用 disposable.dispose(), 序列订阅事件完毕 或者有错时 会销毁, 不再响应
var observer:AnyObserver<Any>?
var observable:Observable<Any>?
weak var weakObservable: Observable<Any>?
1. Observable<Any>.create{ self }
self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
self.test() //1循环引用
print("观察者发送")
anyObserver.onNext("持有了observable,1循环了")
return Disposables.create()
}
public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> {
AnonymousObservable(subscribe)//内部保存了闭包subscribe
}
final private class AnonymousObservable<Element>: Producer<Element> {
...
init(_ subscribeHandler: @escaping SubscribeHandler) {
self._subscribeHandler = subscribeHandler
}
}
引用关系
self
->
AnonymousObservable
->
SubscribeHandler
->
self
所以如果不保存observable是没有循环引用的:
let observable = Observable<Any>.create { (anyObserver) -> Disposable in
print(self) //没有循环引用
anyObserver.onNext("不保存observable")
anyObserver.onCompleted()
return Disposables.create()
}
2. observable.subscribe { self }
//循环引用:持有了
self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
print("观察者发送")
anyObserver.onNext("持有了observable,1循环了")
return Disposables.create()
}
self.observable?.subscribe({ (text) in
print("持有订阅收到")
self.test() //1循环引用
}).disposed(by: disposeBag)
引用关系
self
->
DisposeBag
->
BinaryDisposable
->
SinkDisposer
->
AnonymousObservableSink
->
AnonymousObserver
->
EventHandler
->
onNext
->
self
所以使用时要用weak:
self.observable?.subscribe({ [weak self](text) in
print("持有订阅收到")
self.test() //1循环引用
}).disposed(by: disposeBag)
3. Disposables.create{ self }
self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
print("观察者发送")
anyObserver.onNext("持有了observable,1循环了")
anyObserver.onCompleted()
return Disposables.create{
self.test() //1循环引用
}
}
引用关系
self
->
AnonymousObservable
->
SubscribeHandler
->
AnonymousDisposable
->
DisposeAction
->
self
所以使用时可以不保存observable或者使用weak:
let obser = Observable<Any>.create {(anyObserver) -> Disposable in
print("观察者发送")
anyObserver.onNext("未持有了observable,未循环了")
return Disposables.create{
self.test() //未循环引用
}
}
self.observable = Observable<Any>.create {[weak self] (anyObserver) -> Disposable in
print("观察者发送")
anyObserver.onNext("持有了observable,weakl ,未循环了")
return Disposables.create{
self.test() //未循环引用
}
}
第二种情况
///没有循环引用:没有持有,没有completed
let obr = Observable<Any>.create { (anyObserver) -> Disposable in
anyObserver.onNext("没持有observable,没循环")
return Disposables.create {
self.test()//2循环
}
}
//如有这个,2处就循环了
let dispose = obr.subscribe { (text) in
print(text)
}
dispose.disposed(by: self.disposeBag)
引用关系
self
->
DisposeBag
->
BinaryDisposable
->
SinkDisposer
->
AnonymousDisposable
->
DisposeAction
->
self
想要释放要发送完成事件:
.complete
事件时, rx 内部会自动调用disposable.dispose()
.
let obr = Observable<Any>.create { (anyObserver) -> Disposable in
anyObserver.onNext("没持有observable,没循环")
anyObserver.onCompleted() // .complete 事件时, rx 内部会自动调用 disposable.dispose().
return Disposables.create {
self.test()//2循环
}
}
//如有这个,2处就循环了
let dispose = obr.subscribe { (text) in
print(text)
}
dispose.disposed(by: self.disposeBag)
具体示例
没有循环引用: weak complete
self.observable = Observable<Any>.create {[weak self] (anyObserver) -> Disposable in
self?.test() //1没有循环引用
print("观察者发送2")
anyObserver.onNext("持有了observable,weak 1、2没循环,")
anyObserver.onCompleted()
return Disposables.create{
self?.test() //1没有循环引用
}
}
self.observable?.subscribe({ (text) in
print("持有订阅收到2")
self.test() //2没有循环引用, completed了
}).disposed(by: disposeBag)
使用weak,没有循环引用
self.weakObservable = Observable<Any>.create { (anyObserver) -> Disposable in
self.test() //没循环引用
anyObserver.onNext("weak 没持有observable")
return Disposables.create{
self.test() //没循环引用
}
}
//不会执行,因为没有对象持有上面返回的
//xpression produced error: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
//The process has been returned to the state before expression evaluation.
self.weakObservable?.subscribe({ (text) in
print("不会执行,因为没有对象持有上面返回的")
}).disposed(by: disposeBag)
没有循环引用:没有持有,没有completed
let obr = Observable<Any>.create { (anyObserver) -> Disposable in
self.test() //1没循环引用,没有completed,这里也不会
anyObserver.onNext("没持有observable,没循环")
return Disposables.create {
//2没循环,没有订阅
//2没循环,如有对应的订阅obr.subscribe,有completed
//2循环,如有对应的订阅obr.subscribe,没有completed
self.test()
}
}
//如有这个,2处就循环了
let dispose = obr.subscribe { (text) in
print(text)
}
dispose.disposed(by: self.disposeBag)
没有循环引用:没有持有,但是completed,
let obser = Observable<Any>.create { (anyObserver) -> Disposable in
self.test() //没循环引用,没有completed,这里也不会
anyObserver.onNext("没持有observable,有completed,没循环")
anyObserver.onCompleted()
return Disposables.create{
//2没循环,有对应的订阅obr.subscribe,有completed
self.test()
}
}
let dispose = obser.subscribe { (text) in
print(text)
self.test() //没循环,因为complete
}
dispose.disposed(by: self.disposeBag)
循环引用: 没有持有,没有completed
let obsee = Observable<Any>.create { (anyObserver) -> Disposable in
self.test() //没有循环
anyObserver.onNext("1、2 都可以造成循环,没有completed")
return Disposables.create{
self.test() //1此处循环引用,未持有,有订阅,没weak
}
}
let dispose = obsee.subscribe { (text) in
print(text)
self.test() //2此处循环引用,未持有,没complete,没weak
}
dispose.disposed(by: self.disposeBag)
没有循环引用:没有持有,但是weak了
let obsee2 = Observable<Any>.create {[weak self](anyObserver) -> Disposable in
self?.test()
anyObserver.onNext("1、2没有循环引用:没有持有,但是weak了")
return Disposables.create{
self?.test() //1没有循环引用,未持有,weak了
}
}
let dispose2 = obsee2.subscribe {[weak self] (text) in
print(text)
self?.test() //2没有循环引用,未持有,weak了
}
// let dispose2 = obsee2.subscribe { (text) in
// print(text)
// self.test() ////2循环引用,因为没complete
// }
dispose2.disposed(by: self.disposeBag)
循环引用链:self -> observer -> onNext{} -> self
Observable<Any>.create { (observer) -> Disposable in
self.observer = observer
observer.onNext("Hello")
return Disposables.create()
}
//.subscribe(onNext: { [weak self](value) in
.subscribe(onNext: {(value) in
print(value)
self?.test()//循环引用了,需要weak处理
})
.disposed(by: disposeBag)
self.observer?.onNext("hello world")
控制器相关
//VC1 点击屏幕 push到控制器VC2
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let weakCtrl = CCTestWeakCtrl()
// 订阅控制器2中的可观察序列
weakCtrl.publicOB.subscribe(onNext: { (value) in
print("\(value)")
}).disposed(by: self.disposeBag)
self.navigationController?.pushViewController(weakCtrl, animated: true)
}
// 创建外部可订阅的序列
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
return mySubject.asObservable()
}
// 点击屏幕 发出信号
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
mySubject.onNext("RxSwift")
}
上述代码测试,不会引起循环引用
,只是订阅没释放
:
第一次跳转:VC1上跳转过去VC2,点击屏幕,响应输出一个RxSwift,VC2控制器也释放了;
第二次跳转:返回 VC1后. 在点击跳转到VC2,点击屏幕,响应输出一个RxSwift,VC2控制器也释放了,
只有当VC1释放的时候,对应订阅就释放了,
其实是:
通过RxSwift 申请
的所有资源数量
检查, viewDidAppear 等生命周期函数中加入打印当前资源数量, 发现 跳转一次V2,就会叠加一次, 意味着我们的订阅并没有释放
怎么
查看
RxSwift的资源数量
Podfile文件最后面添加如下代码,重新pod install
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'RxSwift'
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['-D', 'TRACE_RESOURCES']
end
end
end
end
end
上述测试资源数量
====V1 didAppear:116
====V2 didAppear:125
next(RxSwift)
点击返回V1:
====V1 didAppear:125
+++++V2 deinit
再次进入V2
====V2 didAppear:126
RxSwift
点击返回V1:
====V1 didAppear:126
+++++V2 deinit
再次进入V2
====V2 didAppear:127
结果:来回进入,数值逐步增加
正常引用计数
====V1 didAppear:116
====V2 didAppear:134
next(RxSwift)
点击返回V1:
====V1 didAppear:134
+++++V2 deinit
再次进入V2:
====V2 didAppear:134
next(RxSwift)
再次返回V1:
====V1 didAppear:134
+++++testWeak deinit
结果:来回进入,数值不变
方法一
bag 在控制其中只是一个属性的角色
这个要理解, 之前写法中我们将订阅释放写入了外面的 vc 的 bag 中, 而 vc1 的 bag 并没有释放, 因此我们改为写入 vc2 的 bag 中. 当vc2 释放, bag 被销毁, bag中的序列订阅也同样被销毁.
weakCtrl.publicOB.subscribe(onNext: { (value) in
print("\(value)")
}).disposed(by: weakCtrl.disposeBag)
方法二
使用 takeUntil , 意味着该序列订阅保存到什么时候会销毁.
传递 vc.rx.deallocated , 其实跟第一种方法 原理是相同的.
_ = weakCtrl.publicOB.take(until: weakCtrl.rx.deallocated).subscribe { (value) in
print("\(value)")}
}
三:持有控制器VC对象:
vc2 的 viewWillDisappear 时, 调用 onCompleted
, rx 内部会自动调用 disposable.dispose()
,
序列订阅事件完毕 或者有错时 会销毁, 不再响应,
vc1 每次订阅时都产生一个新的 subject
. 这样就在不会产生循环引用的前提下, 持续响应 vc2 的事件;
VC1 跳转进入VC2, VC2返回,在从VC1进入VC2,在VC2点击发送事件,VC1中订阅消息会有多次输出
self.testVC?.publicOB.subscribe(onNext: { (value) in
print("\(value)")
}).disposed(by: disposeBag)
self.navigationController?.pushViewController(vc, animated: true)
解决方式
// vc2
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
mySubject.onCompleted()
}
// 创建外部可订阅的序列
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
mySubject = PublishSubject<Any>()
return mySubject.asObservable()
}
网友评论