来源:  对月流

链接:http://www.jianshu.com/p/f1393d10109d

写在前面:

关于KVC和KVO各种博客多了去了,重新整理下,就当是温习一下吧,也还算是个新手,不对的地方请指教,喜欢的点个喜欢什么也是挺好。

一,KVC

KVC也就是key-value-coding,即键值编码,通常是用来给某一个对象的属性进行赋值,例如有人这么一个类,其对外有两个属性,姓名和年龄,我们在创建了一个人p后可以通过点语法直接给p赋值。

Person *p = [[Person alloc] init];
p.name = @"张三";
p.age = ;

我们也可以通过kvc给这个人p赋值,代码如下,因为setValue这里的值是id类型的,所以将整数包装成一个对象

[p setValue:@"张三" forKey:@"name"];
[p setValue:@ forKey:@"age"];

但是我们这样去赋值显得多此一举,可是如果人这个类的属性是没有暴露在外面呢?比如现在给人这个类一个私有的身高的属性,并且对外提供一个输出身高的接口,如下

#import "Person.h"
@implementation Person
{
NSInteger _height;
} - (void)logHeight
{
NSLog(@"%ld",_height);
}
@end

这时候我们是没有办法去给人p直接设置身高的,外面我们访问不到它.但是有了kvc就不一样了。

[p setValue:@ forKey:@"height"];

我们通过kvc可以直接对私有属性进行赋值,打印如下

除了[p setValue:@170 forKey:@"height"]这个方法外,还有一个方法也是可以对私有属性进行赋值的[p setValue:@170 forKeyPath:@"height"];这两个方法对于一个普通的属性是没有区别的,都可以用,但是对于一些特殊的属性就有区别了。

比如说人这个类有个属性是狗,狗又有属性体重。

  p.dog = [[Dog alloc] init];
[p setValue:@ forKey:@"dog.weight"];

如果我们直接这样是会报错说找不到dog.weight这个key的,而在storyboard中,我们拖控件连线错误的时候也会报错说找不到什么key,说明storyboard在赋值的时候也是通过kvc来操作的。

这里如果我们换另外的一个方法,这时候是不会报错的,而且可以打印出狗的体重.

[p setValue:@200forKeyPath:@"dog.weight"];

说明forKeyPath是包含了forKey这个方法的功能的,甚至forKeyPath方法还有它自己的高级的功能,它会先去找有没有dog这个key,然后去找有没有weight这个属性。所以我们在使用kvc的时候,最好用forKeyPath这个方法。

最后还有一点,如下代码

[p setValue:@ forKey:@"height"];

我们传入的字符串key是height,但是定义的属性是_height,但是通过kvc还是可以给_height属性赋到值。说明对某一个属性进行赋值,可以不用加下划线,而且它的查找规则应该是:先查找和直接写入的字符串相同的成员变量,如果找不到就找以下划线开头的成员变量。

kvc除了访问私有变量这个用处外,还可以用于字典转模型。在Person类对外提供一个接口,将转模型的工作放在模型中进行

- (instancetype)initWithDict:(NSDictionary *)dict
{ if (self = [super init]) { [self setValuesForKeysWithDictionary:dict]; }
returnself;
}

外面可以直接将字典传入,和平常转模型相比,kvc更加方便,减少了代码量。

NSDictionary*PersonDict = @{@"name":@"李四",@"age":@""};
Person *p2 = [Person personWithDict:PersonDict];
NSLog(@"name = %@,age =%ld",p2.name,p2.age);

所以kvc最常见的两种用法就是:

1,对私有变量进行赋值

2,字典转模型

但是也有一些需要注意的地方

1,字典转模型的时候,字典中的某一个key一定要在模型中有对应的属性

2,如果一个模型中包含了另外的模型对象,是不能直接转化成功的。

3,通过kvc转化模型中的模型,也是不能直接转化成功的。

既然可以通过kvc赋值,同样的也可以通过它进行取值。

NSLog(@"name=%@",[p2valueForKey:@"name"]);
NSLog(@"dogweight=%@", [p2.dogvalueForKeyPath:@"@p2.dog"]);

二,KVO

KVO,即key-value-observing,利用一个key来找到某个属性并监听其值得改变。其实这也是一种典型的观察者模式。

简单的说,kvo的用法非常简单。

1,添加观察者

2,在观察者中实现监听方法,observeValueForKeyPath: ofObject: change: context:(通过查阅文档可以知道,绝大多数对象都有这个方法,因为这个方法属于NSObject)

3,移除观察者

具体代码如下:

//让对象b监听对象a的name属性
//options属性可以选择是哪个
/*
NSKeyValueObservingOptionNew =
0x01, 新值
NSKeyValueObservingOptionOld =
0x02, 旧值
*/
[a addObserver:b forKeyPath:@"name"options:kNilOptionscontext:nil];
a.name = @"zzz"; #pragma mark - 实现KVO回调方法
/*
* 当对象的属性发生改变会调用该方法
* @param keyPath 监听的属性
* @param object 监听的对象
* @param change 新值和旧值
* @param context 额外的数据
*/ - (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary
*)change context:(void *)context
{
NSLog(@"%@的值改变了,",keyPath);
NSLog(@"change:%@", change);
} //最后不要忘记,和通知一样,要在dealloc方法里面移除监听 - (void)dealloc
{ [a removeObserver:bforKeyPath:@"name"]; }

KVO的底层实现

当一个类的属性被观察的时候,系统会通过runtime动态的创建一个该类的派生类,并且会在这个类中重写基类被观察的属性的setter方法,而且系统将这个类的isa指针指向了派生类,从而实现了给监听的属性赋值时调用的是派生类的setter方法。重写的setter方法会在调用原setter方法前后,通知观察对象值得改变。

具体实现图如下,这里我拿的是iOS程序猿的图,借用一下应该没关系吧?

最后

貌似有个facebook开源的工具,KVOController ,是一个简单安全的 KVO(Key-value Observing,键-值 观察)工具,好像挺好用的。

iOS:KVC和KVO的更多相关文章

  1. iOS KVC 和 KVO 的学习

    KVC  (NSKey Value Coding) :键值编码 KVO (Key Value Observing) :键值监听 前言:我曾经用过 监听 一个音频何时结束 监听视频播放 状态等 用了这种 ...

  2. [iOS] KVC 和 KVO

    开发iOS经常会看见KVO和KVC这两个概念,特地了解了一下. 我的新博客wossoneri.com link KVC Key Value Coding KVC是一种用间接方式访问类的属性的机制.比如 ...

  3. iOS KVC 和 KVO 区别简单总结

    KVC: key value coding,键值编码.是一种通过使用属性的名称(key)来间接访问对象属性的方法.这个方法可以不用通过 setter/getter 方法来访问对象的属性.该方法使用的实 ...

  4. 【原】iOS中KVC和KVO的区别

    在iOS开发中经常会看到KVC和KVO这两个概念,比较可能混淆,特地区分一下 KVC(Key Value Coding) 1> 概述 KVC:Key Value Coding,键值编码,是一种间 ...

  5. iOS中关于KVC与KVO知识点

    iOS中关于KVC与KVO知识点 iOS中关于KVC与KVO知识点  一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCodin ...

  6. iOS开发中KVC、KVO简介

    在iOS开发中,KVC和KVO是经常被用到的.可以使用KVC对对象的属性赋值和取得对象的属性值,可以使用KVO监听对象属性值的变化.简单介绍一下KVC和KVO. 一:键值编码(KVC) KVC,全称 ...

  7. iOS开发-KVC和KVO的理解

    KVC和KVO看起来很专业,其实用起来还是比较简单的,KVC(Key-value coding)可以理解为键值对编码,如果对象的基本类型,那么键值对编码实际上和get,set方法没有区别,如果是属性是 ...

  8. iOS编程——Objective-C KVO/KVC机制[转]

    这两天在看和这个相关的的内容,全部推翻重写一个版本,这是公司内做技术分享的文档总结,对结构.条理做了更清晰的调整.先找了段代码,理解下,网上看到最多的一段的关于KVC的代码 先上代码 1.     1 ...

  9. 【iOS】KVC 与 KVO

    一.KVC与KVO *"KVC":key value Coding(键值编码) *目的:间接的改动或获取对象的属性,减少程序(类与类)之间的耦合度. *"KVO" ...

随机推荐

  1. redis 的优化

    1.pipeling “请求-响应”模式的服务器在处理完一个请求后就开始处理下一个请求,不管客户端是否读取到前一个请求的响应结果.这让客户端不需要发一个请求等一个响应的串行,可以一次发送多个请求,再最 ...

  2. SPOJ 375

    默默一看提交时间 -- 这是我以前的代码风格-- #include <cstdio> #include <cstring> #include <vector> #i ...

  3. 云联云通讯报错:应用与模板id不匹配,解决方法

    <statusMsg>应用与模板id不匹配</statusMsg> 这种一般是后端服务器上配置的APP ID和模板ID所属的APP不一致造成的 找到发送模板短信的方法,修改ap ...

  4. vivo手机的坑-禁止微信浏览器网页点击图片,图片会自动放大

    这个坑让我郁闷极了,之前我的手机在微信浏览器打开网页点击图片时,啥事也没有 现在,咋回事,变了呢! 现在我打开微信浏览器网页面html,点击一个img标签的图片,图片会自动满屏放大,吓死宝宝了.其他人 ...

  5. centos系统服务管理

    系统服务管理工具: chkconfig(所有linux发行版都有),用法很简单,如下: usage:   chkconfig --list [name]          chkconfig --ad ...

  6. ajax向php传参数对数据库操作

    刚入门php,要求要对多用户进行批量删除(当然实际中是不可能的),在这就以此为例. 大意就是通过对数据库中用户查询,将用户信息显示在页面表格中,在进行多项选择后将所选行参数通过ajax传入后台php文 ...

  7. 17-7-25-js记录

    先说明下为什么说好每天一更,周五周六周日都没有更新.因为在周五的时候,上司主动找我谈了转正后的工资4-4.5K.本来想好是6K的,后来打听了一圈公司的小伙伴,都是5-5.5,我就把自己定到了5K.万万 ...

  8. grep 参数

    功能说明:查找文件里符合条件的字符串. 语 法:grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>] ...

  9. 使用appframework前端框架中输入框圆角问题

    目前使用HTML5技术来开发手机跨平台app已经成为了曾经的web开发人员介入移动开发的一条捷径.与此对应也出现了很多新的技术来支撑这样的开发方式,例如国外的phonegap和国内的APPcan等.很 ...

  10. JQuery总结+实例

    JQuery是什么? Jquery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari ...