返回

iOS自定义KVO(一)-属性的监听

IOS

实现步骤

1. 监听setter方法

KVO的核心思想是监听属性的修改,当属性被修改时,通知观察者。在系统中,KVO是通过监听setter方法来实现的。当一个属性被修改时,它的setter方法会被调用,在setter方法中,会调用KVONSKeyValueDidChange方法,通知观察者属性被修改了。

我们可以通过重写setter方法来实现属性的监听。在重写setter方法时,我们需要调用super的setter方法,以便父类的setter方法能够正常执行。然后,我们可以调用NSKeyValueDidChange方法,通知观察者属性被修改了。

-(void)setName:(NSString *)name {
  [super setName:name];
  [self.observationInfo willChangeValueForKey:@"name"];
  [self.observationInfo didChangeValueForKey:@"name"];
}

2. 动态生成子类

在KVO中,当一个类被监听时,系统会动态生成一个该类的子类。这个子类继承自父类,并重写了父类的setter方法。在重写的setter方法中,子类会调用KVONSKeyValueDidChange方法,通知观察者属性被修改了。

我们可以使用objc_allocateClassPair方法来动态生成一个子类。在生成子类时,我们需要指定父类和子类的名称。然后,我们可以使用objc_registerClassPair方法将子类注册到系统中。

Class cls = objc_allocateClassPair([super class], "MyClass", 0);
objc_registerClassPair(cls);

3. 修改isa指针

在KVO中,当一个对象被监听时,它的isa指针会被修改,指向动态生成的子类。这样,当对象调用setter方法时,就会调用子类的setter方法,从而通知观察者属性被修改了。

我们可以使用object_setClass方法来修改对象的isa指针。在修改isa指针时,我们需要指定对象和新的isa指针。

object_setClass(self, cls);

4. 保存观察者

在KVO中,观察者需要被保存起来,以便在属性被修改时通知观察者。我们可以使用NSHashTable来保存观察者。

NSHashTable *observers = [NSHashTable hashTableWithOptions:NSHashTableWeakMemory];

当一个观察者想要监听一个对象时,它可以调用addObserver:forKeyPath:options:context:方法。在这个方法中,观察者会被添加到对象的观察者列表中。

[observers addObject:observer];

当一个对象的属性被修改时,它会调用NSKeyValueDidChange方法,通知观察者属性被修改了。在NSKeyValueDidChange方法中,对象会遍历观察者列表,并调用每个观察者的observeValueForKeyPath:ofObject:change:context:方法。

for (id observer in observers) {
  [observer observeValueForKeyPath:keyPath ofObject:self change:change context:context];
}

通过以上步骤,我们可以实现iOS中的自定义KVO。