iOS自定义KVO(一)-属性的监听
2023-11-28 17:40:31
实现步骤
1. 监听setter方法
KVO的核心思想是监听属性的修改,当属性被修改时,通知观察者。在系统中,KVO是通过监听setter方法来实现的。当一个属性被修改时,它的setter方法会被调用,在setter方法中,会调用KVO
的NSKeyValueDidChange
方法,通知观察者属性被修改了。
我们可以通过重写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方法中,子类会调用KVO
的NSKeyValueDidChange
方法,通知观察者属性被修改了。
我们可以使用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。