目录

  • 概念

  • 应用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. ssm整合-错误4

    严重: Servlet.service() for servlet [dispatcher] in context with path [/management] threw exception [R ...

  3. 访问本地方站出现EOF的分析和解决

    每天早晨打开电脑运行本地项目的时候,有时候浏览器上会出现EOF 之前都都能正常访问,所以我猜想本地的项目本身肯定是没有问题的. Google了下,发现有人说是代理的问题,于是关闭代理试过后,发现可以访 ...

  4. H5混合开发进阶

    混合开发: 原生app里面,IOS 安卓的原生app里面,嵌套h5界面. 通过原生app里的一个webView盒子进行交互.webView是原生app内置的一个XXX,里面可以放置h5界面.可以相互调 ...

  5. koa2 mongdb 做后端接口的小demo

    现在前端全栈里面有一种技术栈比较火 前端使用 vue 或者react 后端使用 koa2 mysql数据库 或者mongdb做数据储存 但是基本这样的全栈教程 都要收费 收费就收费吧 但是 有没有遇到 ...

  6. STM32(3)——外部中断的使用

    1 .简介 ARM Coetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置.STM32目前支持的中断共84个(16个内部+68个外部),还有1 ...

  7. Linux中程序的编译和链接过程

    1.从源码到可执行程序的步骤:预编译.编译.链接.strip 预编译:预编译器执行.譬如C中的宏定义就是由预编译器处理,注释等也是由预编译器处理的. 编译: 编译器来执行.把源码.c .S编程机器码. ...

  8. vue---day03

    1. Vue的生命周期 - 创建和销毁的时候可以做一些我们自己的事情 - beforeCreated - created - beforeMount - mounted - beforeUpdate ...

  9. Codeforces 845 C Two TVs

    参考:https://blog.csdn.net/xjh_shin/article/details/77491693 #include <iostream> #include <cs ...

  10. Python入门及容易!网摘分享给大家!

    Python:Python学习总结 背景 PHP的$和->让人输入的手疼(PHP确实非常简洁和强大,适合WEB编程),Ruby的#.@.@@也好不到哪里(OO人员最该学习的一门语言). Pyth ...