KVO学习笔记

2020-12-07  本文已影响0人  会跑的鱼_09

使用时小技巧

一、自动开关automaticallyNotifiesObserversForKey:,如果返回NO则对应的字段监听就需要手动触发了,在set方法中把变量的修改用willChangeValueForKey:和didChangeValueForKey:包裹

- (void)setNick:(NSString *)nick{
    [self willChangeValueForKey:@"nick"];
    _nick = nick;
    [self didChangeValueForKey:@"nick"];
}

二、如果想对监听key做一个转换,例如想监听keyA,实际内容需要监听B和C两个属性的变化,通过keyPathForValuesAffectingValueForKey:进行转换即可

+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key{
    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
    if ([key isEqualToString:@"downloadProgress"]) {
        NSArray *affectingKeys = @[@"totalData", @"writtenData"];
        keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys];
    }
    return keyPaths;
}

三、对于数组的观察需要利用kvc的技术来进行

//有这样一个对象,有一个NSMutableArray的属性
@interface LGPerson : NSObject
@property (nonatomic, strong) NSMutableArray *dateArray;
@end

//监听其属性变化 
[self.person addObserver:self forKeyPath:@"dateArray" options:(NSKeyValueObservingOptionNew) context:NULL];

//只有通过kvc的方法修改属性才能触发kvo的监听回调
[[self.person mutableArrayValueForKey:@"dateArray"] addObject:@"1"];

KVO的原理

1.动态生成子类NSKVONotifiy_A,修改当前对象的isa,这样才进行消息转发时才会进到子类的方法列表中来。
2.动态给子类添加setter方法,class方法,dealloc方法,_isKVOA方法。setter方法是为了能拦截赋值过程通知给观察者,class方法是为了调用[object class]方法时不对外暴露子类的信息,dealloc方法是为了在对象释放时把isa指回来,_isKVOA方法是为了标记当前类的是用于kvo的。
3.在动态生成的setter方法中把消息转发给父类,调用父类的setter方法,并通知观察者属性变化。
具体过程推荐学习iOS-底层原理 23:KVO 底层原理

上一篇下一篇

猜你喜欢

热点阅读