KVC与KVO的实现原理
|KVC的用法
1、KVC既键值编码(Key Value Coding),基于NSKeyValueCoding协议,它是以字符串的形式来操作对象的成员变量,也就是通过字符串key来指定要操作的成员变量。基本操作如:
- setValue:forKey:为成员变量赋值。如:[student setValue:@"大明" forKey:@"name"];
- valueForKey:获取指定的成员变量。如:NSString *name = [student valueForKey:@"name"];
2、用KVC操作成员变量的底层实现,就拿成员变量name来说吧,一般按如下顺序执行:
- 程序先尝试调用name的setter或getter方法,就是先调用setName或name方法来设置或获取成员变量。
- 如果该类没有提供setter或者getter方法,则KVC机制将会搜索该类中名为_name的成员变量。这时无论该成员变量定义在接口部分还是实现部分,KVC的代码底层都会对_name进行赋值或者获取操作。
- 如果该类既没有setter或者getter方法,也没有_name成员变量,则KVC机制将会搜索该类中名为name的成员变量。这时无论该成员变量定义在接口部分还是实现部分,KVC的代码底层都会对name进行赋值或者获取操作。
- 如果以上3步都没能找到指定的成员变量,则程序将会执行setValue:forUndefinedKey:或者valueForUndefinedKey:方法抛出异常,默认是终止程序。
3、对于不存在的key怎么处理呢?默认情况下会抛出NSUnknownKeyException异常,并终止程序。
此时可以直接在类的实现部分重写setValue:forUndefinedKey:和valueForUndefinedKey:方法,当KVC找不到指定的成员变量时,会调用这两个方法,通过重写这两个方法可以方便的定制自己的处理方案。
4、setNilValueForKey:方法的调用。
当用KVC的方式把基本数据类型(如int、float等)设置为nil时,会调用成员变量所属类的setNilValueForKey:方法,抛出NSInvalidArgumentException异常,并终止程序。
此时在该类的实现中重写setNilValueForKey:做相应的处理即可。
5、KVC操作对象的复合属性。
复合属性:一个类的属性是另一个类的对象,这个对象的属性就是就是复合属性,比如Person类有个Student类型的属性student,Student类有个name属性,name相对于Person类就是个复合属性。这个复合属性在KVC机制中被称为key路径,即student.name。
在KVC机制中操作key路径的方法如下:
- setValue:forKeyPath:根据key路径设置属性值。
- valueForKeyPath:根据key路径获取属性值。
通过KVC操作对象的性能比通过setter和getter方法要差,但是通过KVC比较灵活。
|KVO的用法
KVO即键值监听(Key Value Observe),基于NSKeyValueObserving协议,用于监听属性值的改变(通常是数据模型)。
KVO的用法分三步:
- 为对象指定的key路径注册监听器 -> addObserver:forKeyPath:options:context:。
- 重写监听方法以得到最新修改的数据 -> observeValueForKeyPath:ofObject:change:context:。
- 删除指定key路径的监听器 -> removeObserver:forKeyPah:或者removeObserver:forKeyPath:context。
参数说明:
observer: 观察对象。
forKeyPath:对象的复合属性。
options分别是:
- NSKeyValueObservingOptionNew:把更改之前的值提供给处理方法
- NSKeyValueObservingOptionOld:把更改之后的值提供给处理方法
- NSKeyValueObservingOptionInitial:把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。
- NSKeyValueObservingOptionPrior:分2次调用,在值改变之前和值改变之后。
- 0:就代表不带任何参数进去。
context: 可以带入一些参数,其实这个挺好用的,任何类型都可以,自己强转就好了。
change: 字典里的key对应options里的NSKeyValueObservingOptionNew、NSKeyValueObservingOptionOld等。
#import "ViewController.h"
#import "Person.h"
#import "Student.h" @interface ViewController ()
@property (strong, nonatomic) Person *person;
@property (strong, nonatomic) Student *stu;
@end @implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *person = [[Person alloc] init];
self.person = person;
Student *stu = [[Student alloc] init];
self.stu = stu;
person.height = 1.5;
person.student = stu;
stu.height = 1.0;
stu.age = ;
[person addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil];
[person addObserver:self forKeyPath:@"student.height" options:NSKeyValueObservingOptionNew context:nil];
[stu addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
for (int i = ; i < ; i++) {
[person setValue:@(person.height + i) forKey:@"height"];
[person setValue:@(person.student.height + i) forKeyPath:@"student.height"];
[stu setValue:@(stu.age + i) forKey:@"age"];
} NSLog(@":person.height = %@, stu.height = %@, stu.age = %@", [person valueForKey:@"height"], [person valueForKeyPath:@"student.height"], [stu valueForKey:@"age"]);
} - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
NSLog(@"\n--------------------\n被修改的KeyPath:%@\n被修改的对象:%@\n被修改后的值:%@\n被修改的上下文:%@\n\n\n", keyPath, object, change[NSKeyValueChangeNewKey], context);
} - (void)dealloc {
[self.person removeObserver:self forKeyPath:@"height"];
[self.person removeObserver:self forKeyPath:@"student.height"];
[self.stu removeObserver:self forKeyPath:@"age"];
} @end
KVC与KVO的实现原理的更多相关文章
- KVC和KVO的理解(底层实现原理)
1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的 ...
- KVC 和 KVO 简单总结
KVC: key value coding,键值编码.是一种通过使用属性的名称(key)来间接访问对象属性的方法.这个方法可以不用通过 setter/getter 方法来访问对象的属性.该方法使用的实 ...
- iOS中关于KVC与KVO知识点
iOS中关于KVC与KVO知识点 iOS中关于KVC与KVO知识点 一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCodin ...
- 聊聊 KVC 和 KVO 的高阶应用
KVC, KVO 作为一种魔法贯穿日常Cocoa开发,笔者原先是准备写一篇对其的全面总结,可网络上对其的表面介绍已经够多了,除去基本层面的使用,笔者跟大家谈下平常在网络上没有提及的KVC, KVO进阶 ...
- KVC和KVO
OC中的一个比较有特色的知识点:KVC和KVO 一.KVC操作OC中的KVC操作就和Java中使用反射机制去访问类的private权限的变量,很暴力的,这样做就会破坏类的封装性,本来类中的的priva ...
- iOS开发中KVC、KVO简介
在iOS开发中,KVC和KVO是经常被用到的.可以使用KVC对对象的属性赋值和取得对象的属性值,可以使用KVO监听对象属性值的变化.简单介绍一下KVC和KVO. 一:键值编码(KVC) KVC,全称 ...
- iOS KVC 和 KVO 区别简单总结
KVC: key value coding,键值编码.是一种通过使用属性的名称(key)来间接访问对象属性的方法.这个方法可以不用通过 setter/getter 方法来访问对象的属性.该方法使用的实 ...
- KVC、KVO实现过程
1.KVC的实现过程 以 [object setValue:@"134567" forKey:@"uid"];为例子,来探究KVC的实现过程 第一步:搜索1.首 ...
- iOS KVC 和 KVO 的学习
KVC (NSKey Value Coding) :键值编码 KVO (Key Value Observing) :键值监听 前言:我曾经用过 监听 一个音频何时结束 监听视频播放 状态等 用了这种 ...
随机推荐
- .NET项目开发的几个非常重要的项目设置
在开发.NET项目的时候,包括Winform项目和Web方面的项目,编译和部署的时候,都需要考虑到是32位的X86方式,还是64位的方式,有时候还需要进行调试,如果没有合理设置好这些关系,还可能出现无 ...
- SignalR入门之持久性连接
为了保持客户端和服务端之间的持久性连接的开发性,并且使用传输在这这样的连接上发送数据,这个用来访问SignalR持久性连接的底层API提供了一个隐藏底层固有复杂性的抽象层. 事实上,通过该API访问通 ...
- IBM和传统IT的沦落
传统IT厂商沦落已经成为一种趋势.不仅仅是在中国去IOE的大背景下,在全球范围内,这些曾经盛极一时的IT大鳄也在衰落.作为一个在IBM服务了将近14年的老员工,我想浅谈一下IBM以及整个传统IT行业的 ...
- C# 图片自由变换 任意扭曲
之前想过要做个地铁驾驶的游戏,其中想把一些原本是矩形图片弄成一个梯形,但是发现GID+上面没有类似的方法.于是在谷歌谷了一下.没有!只能找到令人垂涎的,并没有源码.按照自己的想法尝试了一两天,有点效果 ...
- .net微信公众号开发——消息与事件
作者:王先荣 本文介绍如何处理微信公众号开发中的消息与事件,包括:(1)消息(事件)概况:(2)验证消息的真实性:(3)解析消息:(4)被动回复消息:(5)发送其他消息. 开源项目地址:h ...
- C#编程总结(二)多线程基础
C#编程总结(二)多线程基础 无论您是为具有单个处理器的计算机还是为具有多个处理器的计算机进行开发,您都希望应用程序为用户提供最好的响应性能,即使应用程序当前正在完成其他工作.要使应用程序能够快速响应 ...
- C#的变迁史 - C# 4.0 之并行处理篇
前面看完了Task对象,这里再看一下另一个息息相关的对象Parallel. Parallel对象 Parallel对象封装了能够利用多核并行执行的多线程操作,其内部使用Task来分装多线程的任务并试图 ...
- SSH实例(6)
在WebContent文件夹下新建query.jsp和save.jsp文件. query.jsp: <%@ page language="java" import=" ...
- NoSQL入门概述
入门概述 1 NoSQL是什么? NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL",泛指非关系型的数据库.随着互联网web2.0网站的兴起,传统的关 ...
- SNAT,是源地址转换,其作用是将ip数据包的源地址转换成另外一个地址
SNAT,可能有人觉得奇怪,好好的为什么要进行ip地址转换啊,为了弄懂这个问题,我们要看一下局域网用户上公网的原理,假设内网主机A(192.168.2.8)要和外网主机B(61.132.62.131) ...