博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS KVC与KVO
阅读量:6222 次
发布时间:2019-06-21

本文共 3607 字,大约阅读时间需要 12 分钟。

KVC、KVO概述

  • KVC(NSKeyValueCoding) "键-值 编码"是一种间接访问对象的属性的机制,在Object2.0之后系统提供了(.)语法来访问属性,在此之前我们需要用KVC来访问。
  • KVO(NSKeyValueObserving) "键-值 监听"定义了这样一种机制,当对象属性值发生变化的时候我们能收到一个通知。 注:NSObject类为所有对象提供了一个自动观测能力的NSKeyValueObserving协议。你可以根据具体需求来打开这个监听机制。KVO是根据KVC来实现的。

KVC、KVO的作用

  • KVC是一种间接访问对象属性的机制。 获取属性值时可以通过valueForKey:的方法,设置属性值用setValue: forKey:。与此同时KVC还对未定义的属性值定义了valueForUnderfineKey:,在这里我们需要注意的是KVC中的value都必须是对象。我们可以通过KVC给在m文件中声明的属性进行操作,前提是,我们必须知道这个属性的属性名。
  • KVO是基于KVC来实现的。 系统已经为我们提供了相关的方法,我们只需要注册这个监听,就能很好的监听属性的值发生改变。
  • 注册:下面的方法中,keyPath就是要观察的属性值,options提供的是一个枚举值,就是当键值变化是你可以选择不同的方式,context方便传输你需要的数据。
-(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context复制代码
  • 实现监听方法:其中change里储存了一些数据的变化,比如变化前的数据,变化后的数据。
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void *)context复制代码

KVC键-值 编码

KVC的实现机制

KVC会顺序使用如下技术

  • 检查是否存在getter方法-或者setter方法-set的方法。
  • 如果没有上述方法,则检查是否存在名字为—_、的实例变量。
  • 如果仍未找到,则调用valueForUnderfineKey和setValue:forUnderfineKey:方法。这些方法的默认实现都是抛出异常,我们可以根据需要重写他们。

示例代码

//使用KVC进行属性的间接访问Person *aperson = [[Person alloc]init];[aperson setValue:@"Duck" forKey:@"name"];//等效于aperson.name = @"Duck";[aperson setValue:@"male" forKey:@"gender"];//等效于aperson.sex = @"male";Student *astudent = [[Student alloc]init];[aperson setValue:astudent forKey:@"student"];//通过键值的方式为student属性赋值[aperson setValue:@"Leo" forKeyPath:@"student.name"];//键路径:通过这个方法可以对属性的属性进行操作。复制代码
setValuesForKeysWithDictionary:<#(nonnull NSDictionary
*)#>复制代码

使用这个方法可以将字典里的键值快速的赋值给属性,但是一定要保证属性的名字和字典的键是一致的。如果字典的键多余属性那么就需要我们在这个属性的类中实现下面的一个方法。

-(void)setValue:(id)value forUndefinedKey:(NSString *)key复制代码

KVO键-值 监听者

KVO key - value - observer 观察者观察的是属性是否执行了set方法或者是属性是否使用了KVC赋值,只要有赋值的动作,都会执行KVO的回调方法。如果赋值没有通过set方法或者例如(_name = @"新值",就不会出发KVO回调方法,一般KVO崩溃的原因有两种,第一个原因,被观察的对象是一个局部变量,它已经被销毁掉了。第二个原因,观察者被释放掉了,但是没有移除监听。3,注册的监听没有移除掉,又重新注册了监听)。 首先我们需要注册一个观察者,示例代码如下

[self.view addObserver:self forKeyPath:@"backgroundColor" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];复制代码

options几个枚举选项的意思

NSKeyValueObservingOptionOld 把更改之前的值提供给处理方法NSKeyValueObservingOptionNew 把更改之后的值提供给处理方法NSKeyValueObservingOptionInitial 把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。NSKeyValueObservingOptionPrior 分2次调用。在值改变之前和值改变之后。复制代码
  • observer:观察者(观察对象属性的变化)
  • KeyPath:被观察属性的名称
  • options:观察属性的新值旧值等一些的配置
  • context:可以为KVO的回调方法传值。

KVO的回调方法 当同时监听多个属性的时候,我们需要判断

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void *)context{ if ([keyPath isEqualToString:@"backgroundColor"]) {//view的背景颜色发生了变化 id oldColour = [change objectForKey:NSKeyValueChangeOldKey]; id newcolour = [change objectForKey:NSKeyValueChangeNewKey]; NSLog(@"%@,old==%@",NSKeyValueChangeOldKey,oldColour); NSLog(@"%@,new==%@",NSKeyValueChangeNewKey,newcolour); } if ([keyPath isEqualToString:@"name"]) { id oldValue = [change objectForKey:NSKeyValueChangeOldKey]; id newValue = [change objectForKey:NSKeyValueChangeNewKey]; NSLog(@"%@",oldValue); NSLog(@"%@",newValue); }}复制代码
  • keyPath:属性名称
  • object:被观察的对象
  • change:变化前后的值都存储在字典中
  • context:注册观察者的时候context传过来的值

移除监听的方法 一定要在我们不需要监听的时候,移除监听,不然可能会造成程序崩溃。

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context NS_AVAILABLE(10_7, 5_0);- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;复制代码

至此有关于KVC和KVO的相关知识解释完成,还有其他不足之处,欢迎提出意见。

转载于:https://juejin.im/post/5c1a0dfee51d4542d8471ff6

你可能感兴趣的文章
HA高可用集群之drbd详解
查看>>
关于linux系统安装大于2TB(UEFI接口)硬盘的解决方法
查看>>
我的友情链接
查看>>
Invalid content was found starting with element 'prpperty'.
查看>>
centos7最小化安装
查看>>
我的友情链接
查看>>
Journal - 高级架构 Opencart 主题模板 ABC-0016-04
查看>>
vsftpd服务详解
查看>>
Python13_day3
查看>>
UESTC 2014 Summer Training #16 Div.2
查看>>
使用yum工具下载rpm包
查看>>
NIO入门系列之第7章:文件锁定
查看>>
未来的茫然,或是计划
查看>>
我的友情链接
查看>>
kill
查看>>
项目范围管理论文的提纲
查看>>
Linux基础
查看>>
有的放矢,在性能测试中使用的 10 个微观指标
查看>>
如何修改wordpress博客默认管理员用户名称
查看>>
centos7部署phpipam(ip管理系统)
查看>>