自定义KVO的一些错误使用方式

很多时候我们讲KVO,使用的时候需要注意移除监听,循环引用等问题,但是在自定义KVO的时候,却容易忽视几个问题。

@interface KVOObject : NSObject

@property (strong, nonatomic) NSString *a;
@property (strong, nonatomic) NSString *b;
@property (strong, nonatomic) NSString *c;

@end

@implementation KVOObject
@dynamic c;

- (void)setB:(NSString *)b {
    
}

- (void)setC:(NSString *)c {
    [self willChangeValueForKey:@"c"];
    [self didChangeValueForKey:@"c"];
}

- (NSString *)c {
    return nil;
}

@end

如果是上述对象,分别对a,b,c监听,其结果是怎么样的呢?

结果是a是正常的,b触发一次,但是其变化的结果都是nil,c触发2次,其结果都是nil。我们来分析下这样的结果吧。

首先,系统KVO的实现是什么?是自动创建一个虚拟对象,并重写set方法,那么这就和这个属性是不是真的存在实现(比如空,或者associate object)无关了。所以当我们再次去调用willChangeValueForKeydidChangeValueForKey就产生了2次调用,很多在set方法中再次重申变化是一个错误。

那么我们什么时候需要用到这两个方法呢?当在非set方法里面,通过非set方法变更了属性的值时,就需要手动去触发了。这包括了self->_a这样的调用。

然后,KVO变化的值是怎么取出来的呢?依据willChangeValueForKey的接口来看,并没有传入值的参数,那么显而易见,值是从get方法中取出来的。所以如果set和get方法不是对称的,比如- (id)c所返回的并不是对应c的内容,可能就会出现一些问题,变化的时候并没有触发KVO,触发KVO的时候内容并没有变化。

以上两个在平时碰到的应该比较少,比较自己自定义KVO的场景就比较少。

你可能感兴趣的:(自定义KVO的一些错误使用方式)