KVO底层原理

KVO是key-value-observer的缩写,意思是:当观察的对象的某个属性值发生变化的时候,会通知观察者;是一种观察者的设计模式。

首先就是KVO的使用,我们可以使用

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

这个方法来对对象添加观察者,比如我有一个Person类,有一个name的属性,那么我们可以这样

[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]

为Person类添加观察者,这样可以观察person对象的name属性值得变化,然后我们可以通过下面的方法获取值得改变

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"keyPath = %@, object = %@,change = %@", keyPath, object, change);
}

当然,在使用完后记得移除观察者

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
- 
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

上面是系统提供的两个移除的方法,系统推荐使用的是上面那个带有上下文context的。下面是这个例子的代码

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Person *p1 = [[LJPerson alloc] init];
    p1.name = @"123";
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    [p1 addObserver:self forKeyPath:@"name" options:options context:nil];
    p1.name = @"456";
    [p1 removeObserver:self forKeyPath:@"name"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"keyPath = %@, object = %@,change = %@", keyPath, object, change);
}

上面这种是通过setter方法来触发的,我们也可以通过KVC来触发KVO,比如这样

Person *p1 = [[LJPerson alloc] init];
    [p1 setValue:@10 forKey:@"age"];
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    [p1 addObserver:self forKeyPath:@"age" options:options context:nil];
    [p1 setValue:@22 forKey:@"age"];
    [p1 removeObserver:self forKeyPath:@"age"];

这也就是说明,我们不仅可以用KVO来观察对象属性值得变化,也可以用来观察成员变量值得改变。

接下来就是KVO的底层实现原理(网上抄袭和自身测试):
KVO是以runtime为基础的,在我们对某个对象添加观察者时,以上面的Person类为例,观察person对象的name属性时,runtime会创建一个继承与Person类的子类NSKVONotifiying_Person类,然后将指向person的isa指针指向这个新建的NSKVONotifiying_Person类,在这个类里面,会重写观察的属性的set方法,在这个方法里面调用willChangeValueForkey方法和didChangeValueForKey方法来达到监听的目的。

上面这个是通过setter方法来实现观察者模式的原理,至于KVC模式触发KVO的原理就不懂了,应该是系统内容对KVC进行一系列处理来达到监听目的的。

最后,一定要记得移除观察者,否则会导致崩溃。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值