OC观察者模式之KVO

2019-01-15  本文已影响10人  芝麻酱的简书

KVO:

1.KVO常用API

# observer是观察者,必须实现 
# options:KVO的一些属性配置:
NSKeyValueObservingOptionNew:change字典包括改变后的值
NSKeyValueObservingOptionOld:change字典包括改变前的值
NSKeyValueObservingOptionInitial:注册后立刻触发KVO通知
NSKeyValueObservingOptionPrior:值改变前是否也要通知(这个key决定了是否在改变前改变后通知两次)

- (void)addObserver:(NSObject *)observer 
         forKeyPath:(NSString *)keyPath 
            options:(NSKeyValueObservingOptions)options
            context:(void *)context;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

2.禁用KVO

1). 禁用部分属性的KVO

- (void)setName:(NSString *)name {
    [self willChangeValueForKey: @"name"];
    _name = name;
    [self didChangeValueForKey: @"name"];
}

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    if ([key isEqualToString: @"name"]) {
        return NO;
    }
    return [super automaticallyNotifiesObserversForKey: key];
}

2). 禁用所有属性的KVO
如果需要禁用该类KVO的话直接automaticallyNotifiesObserversForKey返回NO,实现属性的setter方法,不进行调用willChangeValueForKey:didChangeValueForKey方法。

- (void)setName:(NSString *)name {
    _name = name;
}

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    return NO;
}

3.isa混写技术在KVO中实现

派生类中实现:

- (void)setValue:(id)obj {
    [self willChangeValueForKey: @"keypath"];
    [super setValue: obj]
    
    # didChange方法触发监听回调
    [self didChangeValueForKey: @"keypath"];
}

当我们注册一个对象的观察者后,实际上是调用了系统的addObserver:ForKey:path:方法,系统会为我们在运行时动态的创建一个NSKVONotifying_被观察类的名字这样一个类,并将原来被观察的类的isa指针指向新创建的类(这一步就是isa混写技术的标志)。NSKVONotifying_被观察类的名字该类为原被观察类的子类,并重写了setter方法,来达到负责通知所有观察者这一目的。

Objective-C 在发送消息的时候,会通过 isa 指针找到当前对象所属的类对象。而类对象中保存着当前对象的实例方法,因此在向此对象发送消息时候,实际上是发送到了派生类对象的方法。由于编译器对派生类的方法进行了 override,并添加了通知代码,因此会向注册的对象发送通知。注意派生类只重写注册了观察者的属性方法。

4.KVO什么时候会生效:

上一篇 下一篇

猜你喜欢

热点阅读