KVO的本质

KVO 是 Objective-C 对观察者模式的实现。也是 Cocoa Binding 的基础。当被观察对象的某个属性发生更改时,观察者对象会获得通知。

Apple 的文档对KVO的解释:

被观察对象的 isa 指针会指向一个中间类,而不是原来真正的类。

实际上,当你观察一个对象时,一个中间类会被runtime创建出来,新创建出的类继承自该对象的原本的类。并重写的setter方法,重写的 setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象值的更改。并使这个对象isa指针指向了生成的中间类。

@interface Person : NSObject
@property (assign, nonatomic) int age;
@end

如果观察 Personage属性。

  1. 系统会在运行时生成NSKVONotifying_Person

  2. NSKVONotifying_Person中重写setterclassdealloc等方法。

  3. 使Person实例对象的isa指针指向
    NSKVONotifying_Person

  4. NSKVONotifying_Person的superclass指向Person

生成的中间类的大致结构:

NSKVONotifying_Person
isa
superclass
setage
class
dealloc
_isKVOA

重写的class方法会直接返回Person

- (Class)class
{
    return [MJPerson class];
}

在重写的NSKVONotifying_Person的-setAge方法中会调用_NSSetIntValueAndNotify

- (void)setAge:(int)age
{
    _NSSetIntValueAndNotify();
}

因为_NSSetIntValueAndNotify在Foundation框架中,无法查看起具体实现,根据实践猜测大致为代码如下:

void _NSSetIntValueAndNotify()
{
    [self willChangeValueForKey:@"age"];
    [super setAge:age];
    [self didChangeValueForKey:@"age"];
}

- (void)didChangeValueForKey:(NSString *)key
{
    // 通知监听器,某某属性值发生了改变
    [oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
}

注:Foundation框架中类似_NSSetIntValueAndNotify的方法实现还有很多:

__NSSetBoolValueAndNotify
__NSSetCharValueAndNotify
__NSSetDoubleValueAndNotify
__NSSetFloatValueAndNotify
__NSSetIntValueAndNotify
__NSSetLongLongValueAndNotify
__NSSetLongValueAndNotify
__NSSet0bjectValueAndNotify
__NSSetPointValueAndNotify
__NSSetRangeValueAndNotify
__NSSetRectValueAndNotify
__NSSetShortValueAndNotify
__NSSetSizeValueAndNotify

参考:

  • 如何自己动手实现 KVO

你可能感兴趣的:(KVO的本质)