前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >KVC/KVO 本质

KVC/KVO 本质

作者头像
用户1941540
发布2019-02-15 15:40:36
6100
发布2019-02-15 15:40:36
举报
文章被收录于专栏:ShaoYL

KVO 的实现原理

  1. KVO是关于runtime机制实现的
  2. 当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制
  3. 如果原类为Person,那么生成的派生类名为NSKVONotifying_Person
  4. 每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统就会偷偷讲isa指针指向动态生成的派生类,从而在给被监控属性复制是执行的是派生类的setter方法
  5. 键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:和didChangeValueForKey:,在一个被观察属性发生改变之前,willChangeValueForkey:和didChangeValueForKey:;在一个被观察属性发生改变之前,willChangeValueForKey:一定会被调用,这就会记录旧的值。而当改变发生后,didChangeValueForKey:会被调用,继而observeValueForKey:ofObject:change:context:也会被调用
举例伪代码_NSSet*ValueAndNotify
代码语言:javascript
复制
- (void)setAge:(int)age
{
    _NSSetIntValueAndNotify();
}

// 伪代码
void _NSSetIntValueAndNotify()
{
    [self willChangeValueForKey:@"age"];
    [super setAge:age];
    [self didChangeValueForKey:@"age"];
}

- (void)didChangeValueForKey:(NSString *)key
{
    // 通知监听器,某某属性值发生了改变
    [oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
}

KVC的实现原理

  • KVC是Key Value Coding的简称。它是一种可以通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。KVC的方法定义在Foundation/NSKeyValueCoding中。

KVC使用的基本方法:

代码语言:javascript
复制
- (void)setValue:(nullableid)value forKey:(NSString*)key;//通过Key来设值
- (void)setValue:(nullableid)value forKeyPath:(NSString*)keyPath;//通过KeyPath来设值
- (nullableid)valueForKey:(NSString*)key;//直接通过Key来取值
- (nullableid)valueForKeyPath:(NSString*)keyPath;//通过KeyPath来取值
KVC 赋值 setValue:forKey:
  1. setValue:forKey:将键字符串key所对应的属性的值设置为value。(按照setKey:、_setKey:顺序查找方法)如果没有找到Set方法的话,将调用方法setValue:ForUndefinedKey:。并抛出异常 NSUnknowKeyException

2. 若没有找到Set方法,会调用对象的类方法+ (BOOL)accessInstanceVariablesDirectly;此方法返回YES时(默认返回YES),会按照_key,_iskey,key,iskey的顺序搜索成员,然后赋值。

3.  若都没找到成员变量,将调用方法setValue:ForUndefinedKey:。并抛出异常 NSUnknowKeyException

KVC 取值值 valueForKey:
  1. 按先后顺序搜索getKey:、key、isKey、三个方法,若某一个方法被实现,取到的即是方法返回的值,后面的方法不再运行。如果是BOOL或者Int等值类型, 会将其包装成一个NSNumber对象。
  2. 若这三个方法都没有找到,则会调用+ (BOOL)accessInstanceVariablesDirectly方法判断是否允许取成员变量的值。若返回NO,直接调用- (nullable id)valueForUndefinedKey:(NSString *)key方法,并抛出异常 NSUnknowKeyException
  3. 若返回YES,会按先后顺序取_key、_isKey、 key、isKey成员变量的值。调用- (nullable id)valueForUndefinedKey:(NSString *)key方法。
补充
  1. KVC提供属性值正确性验证的API,它可以用来检查set的值是否正确、为不正确的值做一个替换值或者拒绝设置新值并返回错误原因。
代码语言:javascript
复制
- - (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
  1. KVC中的异常.获取值时找不到key- (nullable id)valueForUndefinedKey:(NSString *)key;
  2. 设值时找不到key- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
  3. 给不能设置nil的属性设置了nil。
  • 如果你在SetValue方法时面给Value传nil,则会调用这个方法
  • (void)setNilValueForKey:(NSString *)key;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-01-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • KVO 的实现原理
  • KVC的实现原理
    • KVC使用的基本方法:
      • KVC 赋值 setValue:forKey:
      • KVC 取值值 valueForKey:
      • 补充
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档