美文网首页
ios键值观察KVO

ios键值观察KVO

作者: 我是小胡胡分胡 | 来源:发表于2018-05-03 14:36 被阅读19次

    https://blog.csdn.net/crayondeng/article/details/18842395
    kvo是键值观察的缩写,是一种观察者模式。
    它较完美地将目标对象与观察者对象解耦。

    1, 依赖键,
    依赖键的setter方法被调用了之后, 观察者也能得到通知。
    原有的setter方法修改了,也能得到通知。

    2 ,通知回调中的字典,
    变更前的值,变更后的值NSKeyValueObservingOptionNew, NSKeyValueObservingOptionOld
    {"kind":1,"old":"23456","new":"23456"}

    什么都不加,则字典中无法得到值
    {"kind":1}

    3, 通知被回调次数
    变更之前调用1次
    {"kind":1,"old":null,"notificationIsPrior":true} 变更之前。 只有old

    变更之后调用1次
    {"kind":1,"old":null,"new":"23456"} 变更之后,old和new都有

    4, 是如何触发了通知得到回调的
    willChangeValueForKey调用之后调用{"kind":1,"old":null,"notificationIsPrior":true}

    didChangeValueForKey调用之后调用{"kind":1,"old":null,"new":"23456"}

    setter方法自动增加了willChangeValueForKey和didChangeValueForKey

    如果是手动触发,就需要手动调用willChangeValueForKey,didChangeValueForKey
    [self willChangeValueForKey:@"helloString"];
    [self setHelloString:@"23456"];
    [self didChangeValueForKey:@"helloString"];

    5, 通知回调所在的线程,
    在哪个线程触发的,就在哪个线程执行回调方法observeValueForKeyPath
    默认setter中的willChangeValueForKey, 和didChangeValueForKey的触发是单线程同步的方式运行

    6,原理
    http://blog.sunnyxx.com/2014/03/09/objc_kvo_secret/

    1,当一个object有观察者时,动态创建这个object的类的子类。 重新写class方法,返回原来的类。 但是isa已经是新的类了。
    增加了_isKVOA方法。

    谁被观察了,谁就被isa swizzle了
    keypath如果是多层级的,则.前面的对象的类也被isa swizzle

    2,对于每个被观察的property,重写其set方法===================不对啊。 私有变量并且accessInstanceVariablesDirectly返回NO,返回YES。都没有setter方法。

    3,在子类中 重写的set方法中调用- willChangeValueForKey:和- didChangeValueForKey:通知观察者====== 应该是重写了 willChangeValueForKey 和didchangeValueforkey 通知观察者的。

    property合成的方法。 2,3合适。子类中 确实是重写了 setter方法

    4,当一个property没有观察者时,删除重写的方法
    5,当没有observer观察任何一个property时,删除动态创建的子类

    7,将观察者对象与被观察者对象进行注册与解除注册:
    在dealloc中需要接触注册,否则崩溃
    问题来了,为什么会崩溃?

    8,kvc 变量能不能引发KVO? 能
    kvc 只读变量能不能引发KVO? 能
    变量的直接赋值能不能引发KVO? 不能

    kvc 顺序; 先方法,后实例

    1、getkey key iskey方法
    2、_key,_iskey,key, iskey实例
    3、valueforUndefinedKey


    1、setkey,setnilvalueforkey 类型不是对象类型则崩溃
    2、_key,_iskey,key,iskey实例
    3、setvalue:forundefinedkey:未定义的

    9, [obj addObserver:forKeyPath:options:context:] 参数的意义

    obj : 被观察的对象;
    谁被观察了,谁就被isa swizzle了;
    keypath如果是多层级的,则.前面的对象的类也被isa swizzle

    observer :观察者,就是实现了observeValueForKeyPath:ofObject:change:context:的

    forkeypath: 被观察的对象的属性或者私有变量的key名字,符合kvc搜索路径(属性自动合成了实例变量。非属性:私有实例变量);如果是keypath,则keypath的每一级变化对能导致kvo发生。

    options: 配置;1、回调次数,2、回调方法中change是否带有值,是否有old值/new值 3、是否addobserver后立即调用kvo的回调

    context: 传递给观察者的任意数据

    // 误解的写法。不是错误,只是观察者是self.model,由self.model的类实现通知回调的方法。
    //这句的意思观察者是self.model,self.model需要实现kvo回调方法。 被观察的对象是self,观察的keypath是self的string。 所以当被观察者self存在string属性,string变化了,观察者self.model的kvo回调方法得到回调

    [self addObserver:self.model forKeyPath:@"string" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionPrior context:nil];

    //支持,跟RACObserve(self.model, string)相同
    ///观察者是self,被观察的对象是self.model,观察的keypath是string。当被观察者self.model存在string属性, string变化了,观察者self的kvo回调方法得到回调

    [self.model addObserver:self forKeyPath:@"string" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionPrior context:nil];

    //支持,跟RACObserve(self,model.string)相同
    //观察者是self,被观察的对象是self,观察的keypath是model.string。当被观察者self存在model属性,model存在string属性。 model.string变化了,或者model变化了,kvo回调都会执行,change字典中的值keypath路径中最后一个属性的值。

    //model 和self的类都被重写

    [self addObserver:self forKeyPath:@"model.string" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionPrior context:nil];

    相关文章

      网友评论

          本文标题:ios键值观察KVO

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