返回
苹果开发之旅——KVO简介
IOS
2024-01-26 23:42:38
KVO 简介
KVO是Key-Value Observing
的缩写,意思是“键值观察”。它是一种非正式协议,允许对象在其他对象的指定属性发生更改时得到通知。KVO是建立在KVC(键值编码)的基础上的,因此想要理解KVO,就必须先理解KVC。
KVO 的原理
KVO的原理很简单,它利用了Objective-C的运行时特性。在Objective-C中,每个对象都有一个关联的isa指针,指向该对象的类。当对象的属性发生更改时,它的isa指针也会发生变化。KVO正是利用了这一点来实现的。
当我们使用addObserver:forKeyPath:options:context:
方法为某个对象添加KVO观察者时,KVO会自动创建一个新的isa指针,并将这个新的isa指针与该对象关联起来。这个新的isa指针指向一个KVO派生类,该类继承自对象的原始类,并重写了那些被观察的属性的setter方法。
当被观察的属性发生更改时,KVO派生类的setter方法就会被调用。在setter方法中,KVO会通知所有的观察者,并将属性的新值传递给观察者。
KVO 的使用场景
KVO的使用场景非常广泛,这里列举一些常见的场景:
- 观察模型对象的变化,并在模型对象发生变化时更新UI。
- 观察用户界面的变化,并在用户界面发生变化时更新模型对象。
- 观察应用程序的状态变化,并在应用程序发生状态变化时采取相应的措施。
KVO 的使用示例
下面是一个使用KVO的示例:
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end
@implementation Person
- (void)setName:(NSString *)name {
[self willChangeValueForKey:@"name"];
_name = name;
[self didChangeValueForKey:@"name"];
}
@end
@interface ViewController : UIViewController
@property (nonatomic, strong) Person *person;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 创建一个Person对象
self.person = [[Person alloc] init];
// 为Person对象的name属性添加KVO观察者
[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"name"]) {
// 更新UI
}
}
@end
在这个示例中,我们创建一个Person对象,并为Person对象的name属性添加了一个KVO观察者。当Person对象的name属性发生更改时,KVO观察者就会被调用,并更新UI。
KVO 的缺陷
KVO虽然非常有用,但它也存在一些缺陷:
- KVO会增加内存消耗,因为每个被观察的对象都会创建一个新的isa指针。
- KVO会降低性能,因为KVO的实现需要在运行时动态生成代码。
- KVO的使用可能会导致循环引用,从而导致内存泄漏。
因此,在使用KVO时,我们需要注意这些缺陷,并尽量避免使用KVO来观察那些频繁更改的属性。