RxSwift
对KVO
的调用主要有两种方式:
-
rx.observe
:更加高效,因为它是一个 KVO 机制的简单封装。 -
rx.observeWeakly
: 执行效率要低一些,因为它要判断对象是否被释放
应用场景:
- 在可以使用
rx.observe
的地方都可以使用rx.observeWeakly
。 - 使用
rx.observe
时路径只能包括 strong 属性,否则就会有系统崩溃的风险。而rx.observeWeakly
可以用在weak
属性上。
RxSwift 的KVO比原生KVO用法方便的多:
person.rx.observeWeakly(String.self, "name")
.subscribe(onNext: { (str) in
print("订阅到KVO:\(str)")
})
.disposed(by: disposebag)
同样,KVO分为四个流程:创建序列、订阅、发送、销毁
创建序列
let observable = observeWeaklyKeyPathFor(target, keyPathSections: components, options: options)
.finishWithNilWhenDealloc(target)
-
finishWithNilWhenDealloc(target)
对target进行处理,如果target被释放,则发送nil消息,销毁序列 -
observeWeaklyKeyPathFor
创建一个序列
let property = class_getProperty(object_getClass(target), propertyName)
let propertyAttributes = property_getAttributes(property!)
//propertyAttributes: T@"NSString",N,C,Vname
这2步获取了target(student)
所监听的属性(name)
的属性,即:NSString
类型,N:nonatomic
,C:copy
。如果是W
的话,则代表weak
//创建KVOObservable
let propertyObservable = KVOObservable(object: target, keyPath: propertyName, options: options.union(.initial), retainTarget: false) as KVOObservable
订阅、发送流程
//KVOObservable:
func subscribe(_ observer: Observer) -> Disposable where Observer.Element == Element? {
let observer = KVOObserver(parent: self) { value in
if value as? NSNull != nil {
observer.on(.next(nil))
return
}
observer.on(.next(value as? Element))
}
return Disposables.create(with: observer.dispose)
}
subscribe
创建一个KVOObserver
,继承自:_RXKVOObserver
从下面代码可以看出,RxSwift-KVO其实是对OC的KVO的封装,观察者为KVOObserver
//OC的添加观察
[self.target addObserver:self forKeyPath:self.keyPath options:options context:nil];
//回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
@synchronized(self) {
self.callback(change[NSKeyValueChangeNewKey]);
}
}
当keyPath的值改变时,执行代理方法,回调callback
销毁
KVO的销毁实际意义就是KVOObserver
的disopose()
-(void)dispose {
[self.target removeObserver:self forKeyPath:self.keyPath context:nil];
self.target = nil;
self.retainedTarget = nil;
}
总结:
RxSwift-KVO
实际是对OC KVO
的封装,以中间者模式把观察者移交给KVOObserver
,最后回调响应事件