RxSwift-KVO底层探索(下)

作者: Cooci_和谐学习_不急不躁 | 来源:发表于2019-08-07 19:19 被阅读31次

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

    RxSwift - KVO简介

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

    • rx.observe:更加高效,因为它是一个 KVO 机制的简单封装。
    • rx.observeWeakly : 执行效率要低一些,因为它要处理对象的释放防止弱引用(对象的 dealloc 关系)。

    应用场景:

    • 在可以使用 rx.observe 的地方都可以使用 rx.observeWeakly
    • 使用 rx.observe 时路径只能包括 strong 属性,否则就会有系统崩溃的风险。而 rx.observeWeakly 可以用在 weak 属性上。
    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)
    
    • observeWeaklyKeyPathFor内部创建序列
    • finishWithNilWhenDealloc 针对提前释放的变量的容错,如果对象释放,也就没有观察的必要,写的很不错,毕竟能够观察weak修饰对象
    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>
    
    • 这段代码主要针对观察的keyPath进行处理分析
    • KVOObservable 就是我们的KVO观察的序列,这个对象继承ObservableType,让其具备序列的特性。实现KVOObservableProtocol协议,拓展几个协议属性,常规面向协议编程的思路
    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
        }
    }
    
    • 这段代码,想必大家看完上一篇文章之后非常容易理解,就是我们KVO信息保存者
    • 初始化完毕就是外界flatMapLatest的封装容错

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

    常规订阅,提供给内部: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)
    }
    
    • 核心重点类KVOObserver
    • 保存了一个闭包,我们先看里面,毕竟这里还不能执行
    • KVOObserver这段继承关系是非常重要的
    • 继承_RXKVOObserver,我们查看内部,我的天啊!竟然是一个OC类
    • 实现Disposable协议,具备销毁的能力,用来干嘛,等会讲解
    -(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;
    }
    
    • 这里面针对外界的一些KVO信息处理保存,callback回调的保存,函数式思想
    • [self.target addObserver:self forKeyPath:self.keyPath options:options context:nil];这段代码是比较骚,核心逻辑:观察者移交,我们不在是VC观察,使我们内部类!
    • 观察的keypath有了变化,必然胡响应下面的方法
    -(void)observeValueForKeyPath: ofObject: change: context: {
        @synchronized(self) {
            self.callback(change[NSKeyValueChangeNewKey]);
        }
    }
    
    • 重点就是之前保存的回到函数调用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))
    }
    
    • 我们观察者直接进行了发送响应,这里的value值就是KVO回调的change,完美!序列订阅得以响应

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

    override func dispose() {
        super.dispose()
        self.retainSelf = nil
    }
    
    • 这个dispose的流程是非常简单了,前面我们也有相关分析
    • 核心就是调用了 super.dispose()
    -(void)dispose {
        [self.target removeObserver:self forKeyPath:self.keyPath context:nil];
        self.target = nil;
        self.retainedTarget = nil;
    }
    
    • 只要我们的序列销毁或者订阅关系的销毁的时候就会自动调用dispose
    • 完美看到观察的移除!

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

    相关文章

      网友评论

        本文标题:RxSwift-KVO底层探索(下)

        本文链接:https://www.haomeiwen.com/subject/kimadctx.html