Swift开发进阶RxSwiftiOS 进阶开发

RxSwift-KVO底层探索(下)

2019-08-07  本文已影响31人  Cooci_和谐学习_不急不躁

上面一篇章我们对KVO底层有了一定了解!这一篇我们就开始分析RxSwiftKVO的封装,看完这一篇,你估计也会由衷的感慨:底层源码的思路是有相同的

RxSwift - KVO简介

RxSwiftKVO的调用主要有两种方式:

应用场景:

self.person.rx.observeWeakly(String.self, "name")
            .subscribe(onNext: { (change) in
                print("observeWeakly订阅到了KVO:\(String(describing: change))")
            }).disposed(by: disposeBag)

使用起来非常简单,可读性高,免去传统KVO带来的恶心!下面也粘贴出代码对比一下

// 1: 添加观察
person.addObserver(self, forKeyPath: "name", options: .new, context: nil)
// 2: 观察响应回调
override func observeValue(forKeyPath keyPath:, of object:, change: , context:){}
// 3: 移除观察
person.removeObserver(self, forKeyPath: "name")

RxSwift - KVO底层探索

首先分析在 RxSwift 的世界必然是由序列的,第一步分析序列的创建

中间的细节流程过滤,大家自己查看源码!我们直奔核心,马上要上课!哈哈哈~~~~~~

let observable = observeWeaklyKeyPathFor(target, keyPathSections: components, options: options)
    .finishWithNilWhenDealloc(target)
weak var weakTarget: AnyObject? = target

let propertyName = keyPathSections[0]
let remainingPaths = Array(keyPathSections[1..<keyPathSections.count])

let property = class_getProperty(object_getClass(target), propertyName)
if property == nil {
    return Observable.error(RxCocoaError.invalidPropertyName(object: target, propertyName: propertyName))
}
let propertyAttributes = property_getAttributes(property!)

// should dealloc hook be in place if week property, or just create strong reference because it doesn't matter
let isWeak = isWeakProperty(propertyAttributes.map(String.init) ?? "")

let propertyObservable = KVOObservable(object: target, keyPath: propertyName, options: options.union(.initial), retainTarget: false) as KVOObservable<AnyObject>
init(object: AnyObject, keyPath: String, options: KeyValueObservingOptions, retainTarget: Bool) {
    self.target = object
    self.keyPath = keyPath
    self.options = options
    self.retainTarget = retainTarget
    if retainTarget {
        self.strongTarget = object
    }
}

序列已经创建完毕,下面开始分析订阅,响应发送

常规订阅,提供给内部:AnonymousObserver,这里不讲了,前面的流程非常简单---直接分析重点

func subscribe(_ observer: Observer) -> Disposable {
    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)
}
-(instancetype)initWithTarget:(id)target
                 retainTarget:(BOOL)retainTarget
                      keyPath:(NSString*)keyPath
                      options:(NSKeyValueObservingOptions)options
                     callback:(void (^)(id))callback {
    self = [super init];
    if (!self) return nil;
    
    self.target = target;
    if (retainTarget) {
        self.retainedTarget = target;
    }
    self.keyPath = keyPath;
    self.callback = callback;
    
    // 核心骚操作
    [self.target addObserver:self forKeyPath:self.keyPath options:options context:nil];
    
    return self;
}
-(void)observeValueForKeyPath: ofObject: change: context: {
    @synchronized(self) {
        self.callback(change[NSKeyValueChangeNewKey]);
    }
}
let observer = KVOObserver(parent: self) { value in
    if value as? NSNull != nil {
        observer.on(.next(nil))
        return
    }
    observer.on(.next(value as? Element))
}

下面还缺一个点:关于KVORxSwift的世界里面是不需要移除观察的,下面开始解析

override func dispose() {
    super.dispose()
    self.retainSelf = nil
}
-(void)dispose {
    [self.target removeObserver:self forKeyPath:self.keyPath context:nil];
    self.target = nil;
    self.retainedTarget = nil;
}

总结:纵观RxSwift的KVO流程也就是中间者模式! 移交观察者,到达响应效果。就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!

上一篇下一篇

猜你喜欢

热点阅读