KVO、KVC的实现原理与应用

KVOKVC的实现原理与应用

各种名词:
KVO : key value observing
KVC : key value Coding

KVO 是什么

KVOOC观察者设计模式的一种实现方式,是以非正式协议(Category)的形式定义在NSObject中。
当一个被观察的对象(如类A)的某个属性放生改变时,对象会获得通知,并作出了相应的处理。
MVC设计架构下,KVO是一种理想的ModelView之间的通讯机制。例如,在控制器中创建ModelA的观察者,当ModelA的某个属性发生变化时,可以通过KVO使得控制器收到通知,并作出变化。

KVO的实现原理

举个栗子,当观察对象类ClassApropertyX时,KVO机制会动态的创建ClassA的子类,并且为这个新的子类重现被观察的属性propertyXkeyPathsetter方法。当propertyX发生改变时,会调用setter方法,这时候,setter做了一件事情,那就是通知观察者该属性改变的状态。

那么,iOS 是如何动态创建ClassA的呢?
Apple使用了isa-swizzling来实现KVO的动态创建。当观察ClassA时,KVO会动态的创建一个新的 名为NSKVONotifying_ClassA类,并重写了setter方法,该方法会负责在调用原setter方法之前和之后通知所有观察对象属性值的更改情况。

  1. NSNotifying_ClassA类:在这个过程中,被观察的isa指针(即Runtime中指向对象的类的指针)从指向的是原来的ClassA类,被KVO机制修改为指向NSNotifying_ClassA,用来实现当前类的属性值改变监听。
    当我们手动的创建了NSNotifying_ClassA类,那么就会使得系统运行到注册KVO的那段代码时崩溃。
  2. 子类的setter方法剖析:查看NSObject的两个方法willChangeValueForKey:didChangevlueForKey:,在存取数值的前后分别会调用这两个方法,分别在属性改变前和改变后进行调用。
    KVO为子类的观察者属性重写调用存取方法的工作原理在代码中相当于:
-(void)setName:(NSString *)newName{ 
    [self willChangeValueForKey:@"name"];    //KVO在调用存取方法之前总调用 
    [super setValue:newName forKey:@"name"]; //调用父类的存取方法 
    [self didChangeValueForKey:@"name"];     //KVO在调用存取方法之后总调用
}

观察者观察的是属性,只有遵循了KVO变更属性值的方式才会执行KVO的回调方法,例如是否执行了setter方法、或者是否使用了KVC赋值。
如果赋值的方式没有通过setter方法,那么就只是改变值,不会发出通知。例如,以下方式不会触发KVO机制。

_name = @"newName";

KVO实现步骤

  1. 注册观察者,实施监听
//第一个参数observer:观察者 (这里观察self.myKVO对象的属性变化)
//第二个参数keyPath: 被观察的属性名称(这里观察self.myKVO中num属性值的改变)
//第三个参数options: 观察属性的新值、旧值等的一些配置(枚举值,可以根据需要设置,例如这里可以使用两项)
//第四个参数context: 上下文,可以为kvo的回调方法传值(例如设定为一个放置数据的字典)
[self.myKVO addObserver:self forKeyPath:@"num" options:
NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
  1. 在回调方法中处理属性发生的变化
    当属性(keyPath)的值发生变化时,收到通知,调用以下方法:
// keyPath:属性名称
// object:被观察的对象
// change:变化前后的值都存储在change字典中
// context:注册观察者时,context传过来的值
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
}
  1. 移除观察者

KVCKVO的不同

KVC是一个非正式的Protocol,使用字符串访问一个对象实例变量的机制。而不是通过settergetter方法等显式的存取方式去访问。例如,在动画中,可以使用KVC的方式改变view的参数。
KVO是一种机制,当制定的对象属性被修改后,对象就会接受到通知。

KVOnotification的不同

两者都是一对多,但是对象之间直接的交互,notification明显得多,需要一个中间交互NSNotificationCenter

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值