一、RxSwift内存办理
1.observeWeakly
接下来咱们来看一个比如:
self.person.rx.observe(String.self, "name")
.subscribe(onNext: { change in
print("observe订阅到了KVO:\(String(describing: change))")
}).disposed(by: disposeBag)
self.person.rx.observeWeakly(String.self, "name")
.subscribe(onNext: { change in
print("observeWeakly订阅到了KVO:\(String(describing: change))")
}).disposed(by: disposeBag)
看到了两个不同的observe observeWeakly,别离订阅了name的change。
observe和observeWeakly 有什么区别吗?
1.observe有可能会呈现开释不洁净的状况
2.observeWeakly连weak一同监听处理开释不洁净的状况
进入源码检查:
再次进入observeWeaklyKeyPathFor:
private func observeWeaklyKeyPathFor(_ target: NSObject, keyPath: String, options: KeyValueObservingOptions) -> Observable<AnyObject?> {
let components = keyPath.components(separatedBy: ".").filter { $0 != "self" }
let observable = observeWeaklyKeyPathFor(target, keyPathSections: components, options: options)
.finishWithNilWhenDealloc(target)
if !options.isDisjoint(with: .initial) {
return observable
}
else {
return observable
.skip(1)
}
}
切割字符components 在传入observeWeaklyKeyPathFor 处理返回序列。断点调试看看:
获取到propertyName特点称号,propertyAttributes 特点的具体pointervalue。在经过isWeakProperty 判别是否是弱引证声明。在注册KVOObservable 特点监听。 在propertyObservable.flatMapLatest接纳KVOObservable特点变化监听的回调的容错处理。 这里留意先履行.subscribe订阅闭包 在履行.flatMapLatest闭包。
进入KVOObservable代码:
KVOObservable
承继ObservableType完成KVOObservableProtocol协议
,保存特点,循环订阅特点音讯on(.next)
2.RxSwift-KVO流程
现在咱们看KVOObserver
类,KVOObservable->subscribe->KVOObserver
(parent: self)做了什么。
private final class KVOObserver
: _RXKVOObserver
, Disposable {
typealias Callback = (Any?) -> Void
var retainSelf: KVOObserver?
init(parent: KVOObservableProtocol, callback: @escaping Callback) {
#if TRACE_RESOURCES
_ = Resources.incrementTotal()
#endif
super.init(target: parent.target, retainTarget: parent.retainTarget, keyPath: parent.keyPath, options: parent.options.nsOptions, callback: callback)
self.retainSelf = self
}
override func dispose() {
super.dispose()
self.retainSelf = nil
}
deinit {
#if TRACE_RESOURCES
_ = Resources.decrementTotal()
#endif
}
}
_RXKVOObserver->承继NSObject为什么呢?
第一个想到的是获取目标的特点参数,得到元类信息。
第二个这个可能是个中心类,对rx的特点path进行调查(调查者移送)。
在看super.init->_RXKVOObserver.init
进入断点调试
从断点上看”student.nickName”订阅了两次,一层一层的订阅,在_RXKVOObserver进行KVO特点监听。
然后发现observeWeaklyKeyPathFor
是一个递归调用的办法。
so:回到最初的observeWeakly
便是底层完成了KVO对特点的监听。
3.Rx内存办理
然后咱们在回到KVOObservable
代码看到:
在_RXKVOObserver
在内部也是弱引证接纳target
unowned
var 便是oc中的 unsafe_unretained
相同效果。(为什么用unsafe_unretained而不是weak呢)因为性能更高。
现在咱们看一个比如:
myClosure = { [weak self] in
self?.name = "NY"
}
self.myClosure!()
deinit {
print("\(self)销毁 VC")
}
上面代码假如不加[weak self]
会发生循环引证,这个是基本状况。那假如呈现其他状况呢?
也能够把weak换成unowned也能处理循环引证。
myClosure = { [weak self] in
DispatchQueue.global().asyncAfter(deadline: .now()+2) {
self?.name = "NY"
print(self?.name as Any)
}
}
修正代码添加异步推迟操作2秒,在赋值打印运转程序。
咱们发现并没有崩溃,也没有报错。只是打印nil,可是这个成果并不友好,不利于咱们发现问题。
这么处理nil问题呢,这个代码咱们都会的。再次声明self 为强引证
guard let self = self else { return } //4.2版别之后 保留关键字
self.name = "NY"
print(self.name as Any)
接下来在看一个比如:
self.accountTF.rx.text.orEmpty
.subscribe(onNext:{ text in
self.title = text
}).disposed(by: disposeBag)
会发生循环引证吗? 没有输出销毁VC,这段代码发生了循环引证!!!具体是为什么呢?
修正代码添加 [weak self]
self.accountTF.rx.text.orEmpty
.subscribe(onNext:{ [weak self]text in
self?.title = text
}).disposed(by: disposeBag)
看到运转成果,销毁了VC而且rx计数归0。
核心问题:
那么RX的引证计数是在什么时分销毁归0的呢?
咱们在DisposeBase
中设置断点,运转运转代码调试.
在首页显现,VC销毁之后rx在进行引证计数减法。
继续修正代码:
self.accountTF.rx.text.orEmpty
.bind(to: self.rx.title)
.disposed(by: disposeBag)
这样修正后的代码会发生循环引证吗? 看打印就现已知道,这样修正后没有发生循环引证。为什么呢?rxswift内部是这么处理的呢?
在经过一个比如研究一下:
self.observable = Observable<Any>.create { anyObserver -> Disposable in
anyObserver.onNext("Hello World")
print(self)
return Disposables.create()
}
self.observable?.subscribe(onNext: {
print("订阅到了:\($0) --")
}).disposed(by: self.disposeBag)
在创立序列时打印print(self),这里会发生循环引证吗? 答案是会发生循环引证,并没有销毁VC。 self->observable->create{}->self
这步要留意.subscribe中调用print(self)也会循环引证。
继续看代码:
Observable<Any>.create { anyObserver -> Disposable in
self.observer = anyObserver
anyObserver.onNext("Hello World")
return Disposables.create()
}
.subscribe(onNext: { item in
print(self)
print("订阅到了:\(item)")
})
.disposed(by: self.disposeBag)
这个代码会发生循环引证吗?
答案是会,self -> anyObserver -> subscribe -> self
所以发生了循环引证联系。
let vc = LGDetialViewController()
vc.publicOB.subscribe(onNext:{ item in
print("在\(self)订阅到了\(item)")
}).disposed(by: disposeBag)
这段代码中会发生rxswift计数循环引证,并不是VC页面上的循环引证。 每次点击都会添加rx的引证计数。为什么呢?
咱们看到打印VC并没有销毁,是vc发生了循环引证。怎样处理这个问题呢?怎样销毁掉VC?
当时DetialViewController的disposed用的不应该是用VC的disposeBag。
vc.disposeBag
然后在运转代码
看到了rx计数并没有累加,问处理。
或者运用_ = vc.publicOB.take(until: vc.rx.deallocated)
也能处理问题,使命直到vc.rx.deallocated 详情页销毁的时分完毕。
假如当DetialViewController页是用mySubject.onCompleted()完毕,vc中运用DetialViewController的let dvc声明需要在DetialViewController页中再次激活:
mySubject = PublishSubject<Any>()//激活
总结
-
observeWeakly
:的首要递归函数是observeWeaklyKeyPathFor
对特点进行监听,KVOObservable
是终究接纳监听特点的类。 -
RxSwift-KVO流程
:KVOObservable->subscribe->KVOObserver
->_RXKVOObserver(移送调查者)-OC原生KVO -
Rx内存办理
:unowned
var 便是oc中的unsafe_unretained
相同效果。及在RxSwift中[weak self]的运用,RxSwift本身有针对内部运用的引证计数,首要是用disposeBag来进行维护。subscribe(onNext)和subscribe{}的履行代码不相同,成果也不相同subscribe(onNext)容易呈现循环引证(要留意细节)。