博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
KVO 开发详情
阅读量:6832 次
发布时间:2019-06-26

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

目录

  • 概念

  • 应用KVO的3个步骤

  • 关联属性的KVO

  • 手动管理KVO通知

一、概念

  KVO全称是 Key-Value Observing ,是OC的一种消息发送机制。这个机制是指:假设将B对象注册为A对象的观察者,当A对象的属性发生改变时就会通知它自己的所有观察者包括对象B在内。

  KVO一般用于Controller与Model之间的通信。常见的做法是把Controller注册为Model的观察者,当model改变时Controller就会收到通知并根据新的model来更新View。

  KVO是基于KVC技术的,所以为了理解KVO你必须先了解(还不了解的请移步)。

  需要注意的是,只有两个方式改变对象的属性才会触发KVO通知

    1.通过KVC方法改变(setValue:forKey,setValue:forKeyPath)

    2.通过setter函数(.操作符会调用setter)

  当然你也可以手动管理KVO通知,我们在下面将会讲到

二、应用KVO的3个步骤

  1. 为被观察者注册一个观察者
  2. 观察者接收属性改变的通知
  3. 移除观察者

  1.注册观察者  

//这句代码的意思是 self.observing 观察 self.observed的age属性[self.observed addObserver:self.observing forKeyPath:@"age" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];

  2.接收通知

  在观察者类实现下面方法,当被观察的对象的属性改变时KVO就会调用这个方法。

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void *)context{ NSLog(@"%@ : [%@] => [%@]",keyPath,[change valueForKey:NSKeyValueChangeOldKey],[change valueForKey:NSKeyValueChangeNewKey]); }

  3.移除观察者

  因为注册观察者时,被观察者就持有观察者的强引用,这有这样才能在属性改变时通知观察者。

[self.observed removeObserver:self.observing forKeyPath:@"age"];

   我可以这样有下面代码改变属性,触发KVO通知

// setter[self.observed setAge:@18];// kvc[self.observed setValue:@20 forKey:@"age"];

  如果不出意外应该会输出如果log

age : [0] => [18]age : [18] => [20]

三、关联属性的KVO  

  关联的属性分为两种情况,一对多,多对多

  多对多情况,我们只能通过手动触发KVO等方式来处理

  下面我们来介绍一对多的情况。

  假设Person类有一个readonly的属性 fullName,这个fullName有firstName和lastName组成,下面是fullName的getter函数

-(NSString *)fullName{    return [NSString stringWithFormat:@"%@ %@",self.firstName,_lastName];}

  我们希望当改变firstName或者lastName时可以触发fullName的kvo通知以便告诉其他人,他人只要观察fullName属性就可以了而不需要分别观察firstName跟lastName。

  我们可以有如下函数之一来告诉fullName与fristName、lastName的关联关系

// 单个对象的属性 1+(NSSet *)keyPathsForValuesAffectingFullName{    return [NSSet setWithArray:@[@"firstName",@"lastName"]];}// 单个对象的属性 2+(NSSet
*)keyPathsForValuesAffectingValueForKey:(NSString *)key{ NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; if ([key isEqualToString:@"fullName"]) { NSArray *affectingKeys = @[@"lastName", @"firstName"]; keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys]; } return keyPaths;}

四、手动管理KVO通知

  普通的对象之所以拥有KVO的功能是因为我们的对象都是继承自NSObject类的。

  NSObject帮我实现了一些函数, KVO在适当的时候通过调用这些函数来完成KVO功能。

  其中包过下面两个函数

-(void)willChangeValueForKey:(NSString *)key;-(void)didChangeValueForKey:(NSString *)key;

  我们正式通过自己调用这两个函数来控制KVO的通知的发送,当我们想手动触发age属性的KVO通知时可以这样写:

[self willChangeValueForKey:@"age"]; _age = 18;[self didChangeValueForKey:@"age"];

  当然,最后你得告诉oc说你自己来管理KVO通知

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {    if ([theKey isEqualToString:@"age"]) {        return NO;    }}

转载于:https://www.cnblogs.com/shuigu/p/6351297.html

你可能感兴趣的文章
autotools入门笔记(一)
查看>>
Imagex用法
查看>>
问题集
查看>>
ios实例开发精品文章推荐(7.23)
查看>>
php编译错误Note that the MySQL client library is not bundled anymore或者cannot find mysql header file...
查看>>
Myeclipse--jBPM4.3插件
查看>>
[每日一题] 11gOCP 1z0-053 :2013-10-12 RESULT_CACHE在哪个池?.............................44
查看>>
Unity物理系统的触发器
查看>>
mysql慢查询日志相关参数
查看>>
项目中如果管理前端文件CSS和JS
查看>>
13 jsp include
查看>>
Nginx和PHP-FPM的启动、重启、停止脚本分享(转)
查看>>
如何拷贝CMD命令行文本到粘贴板
查看>>
Oracle数据库—— 存储过程与函数的创建
查看>>
兼容iOS 10 资料整理笔记
查看>>
逻辑回归原理小结
查看>>
php 7.0 安装以及老版本php删除
查看>>
【Machine Learning】决策树案例:基于python的商品购买能力预测系统
查看>>
【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-5 底层驱动之旋转编码器
查看>>
[Erlang]Erlang经常使用工具解说
查看>>