目录

  • 概念

  • 应用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你必须先了解KVC(还不了解的请移步)。

  需要注意的是,只有两个方式改变对象的属性才会触发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<NSString *,id> *)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:@];
// kvc
[self.observed setValue:@ forKey:@"age"];

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

age : [] => []
age : [] => []

三、关联属性的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<NSString *> *)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 = ;
[self didChangeValueForKey:@"age"];

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

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

KVO 开发详情的更多相关文章

  1. ARC中KVO开发注意

    1 在ARC 中 KVO开发 添加监听和去掉监听必需 一一匹配,不要有过的去掉监听否则会有可能导致对象无法释放. 例如,在一个viewcontroller中添加webview 并监听webview的c ...

  2. objective-c runtime 开发详情

    目录 概述 对象与类的实质 id与class 继承关系与isa 总结 C函数创建一个OC类 OC类与runtime NSObjectProtocol NSObject NSProxy 一.概述 Obj ...

  3. iOS 定时器开发详情

    目录 概述 NSTimer performSelector GCD timer CADisplayLink 一.概述 在平时的开发任务中,定时器是我们常用的技术.这一节我们来学习iOS怎么使用定时器. ...

  4. KVC 开发详情

    目录 概述 KVC基本技术 KVC访问函数 KVC搜索顺序 KVC集合操作 一.概述 kvc全名是Key-value coding,kvc是一种通过字符串间接的访问oc对象的属性的一种技术. 一个oc ...

  5. GCD 开发详情

    目录 一.简介 二.dispatch Queue - 队列 三.dispatch Groups - 组 四.dispatch Semaphores - 信号量 五.dispatch Barriers ...

  6. 如何开发Android Wear应用程序

    Android Wear是连接安卓手机和可穿戴产品的一个平台.自从今年上半年发布以来,Android Wear获得了大量关注,既有来自消费者的关注,也有来自开发商的关注,后者希望自己的应用程序已经准备 ...

  7. 微信小程序开发-概述

    微信小程序开发-概述 一.小程序申请&APPID 登录微信平台申请成为小程序开发者,小程序不可直接使用服务号或订阅号的AppID,需要登录微信公众平台管理后台,在网站的"设置&quo ...

  8. jeecms v9开发资料

    开发文档 . 系统架构概述 本系统核心架构为 FreeMarker+hibernate+Spirng 的 mvc 分层架构. 1.1 分层架构模型 img 1.2 数据流转模型 (前端) img . ...

  9. 教你如何开发一个完败Miracast的投屏新功能

      手机与电视,是陪伴在我们生活最常见,陪伴最长久的智能设备.迅猛发展的移动终端与通信技术,赋予了手机更广阔多元的应用生态,大屏电视则以大视野和震撼影音,弥补了手里方寸带来的视觉局限.而今,手机的延伸 ...

随机推荐

  1. 【2018 ICPC焦作网络赛 G】Give Candies(费马小定理+快速幂取模)

    There are N children in kindergarten. Miss Li bought them N candies. To make the process more intere ...

  2. MySql学习笔记06

    课程回顾 一对一关联 案例1:查询每个员工的名字和主管领导的名字 select e.ename 员工姓名,m.ename 领导姓名 from emp e join emp m on e.mgr=m.e ...

  3. 新知识 HtMl 5

    快要毕业了,即将走向实习岗位,但是这日子过的太无聊了,昨天逃课回宿舍打开电脑想看电影但是没什么好看的,于是上床睡觉了,越躺越无聊,然后爬了起来到学习图书馆找了本HTML5的课本,学习了起来(我感觉ht ...

  4. Pro Git 学习笔记

    Pro Git 学习笔记 文档地址:Pro Git原文地址:PRO GIT 学习笔记 git常见命令 1.Git起步 初次运行Git前的配置 用户信息 git config --global user ...

  5. I/O流、字符集

    1)InputStream.OutPutStream是输出输入的基础流,均为抽象类,提供了read和writer方法,所有的子类均实现read和writer方法,read在遇到输入源的结尾时返回-1. ...

  6. Mysql错误积累001-load data导入文件数据出现1290错误

    错误出现情景 在cmd中使用mysql命令,学生信息表添加数据.使用load data方式简单批量导入数据. 准备好文本数据: xueshengxinxi.txt 文件  数据之间以tab键进行分割 ...

  7. 日志框架Log4j

    log4j是一个用Java编写的可靠,快速和灵活的日志框架(API),它在Apache软件许可下发布.Log4j已经被移植到了C,C++,C#,Perl,Python和Ruby等语言中. Log4j是 ...

  8. hive 学习系列五(hive 和elasticsearch 的交互,很详细哦,我又来吹liubi了)

    hive 操作elasticsearch 一,从hive 表格向elasticsearch 导入数据 1,首先,创建elasticsearch 索引,索引如下 curl -XPUT '10.81.17 ...

  9. asp.net core mvc简介

    MVC 通常而言,我们使用.NET Core MVC 构建网页应用与 API,MVC是使用模型-视图-控制器(Model-View-Controller)设计模式. 创建项目 使用如下命令创建一个名称 ...

  10. Java 中编码与摘要算法

    URL 编码与解码 String s = "你好,世界!"; // URL 编码 String urlEncodedString = URLEncoder.encode(s, &q ...