iOS:KVC和KVO

简介:

来源:  对月流      

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

 

写在前面:

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

 

一,KVC

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

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

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

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

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

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

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

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

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

 

 

 

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

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

  p.dog = [[Dog alloc] init];
  [p setValue:@200 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:@170 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":@"18"};
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,键-值 观察)工具,好像挺好用的。

 

程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/5286278.html ,如需转载请自行联系原作者
相关文章
|
存储 iOS开发
iOS Principle:KVO(下)
iOS Principle:KVO(下)
135 0
iOS Principle:KVO(下)
|
存储 C语言 iOS开发
iOS Principle:KVO(上)
iOS Principle:KVO(上)
144 0
iOS Principle:KVO(上)
|
Android开发 iOS开发
iOS开发:KVC与KVO
KVC 就是键值编码(key-value-coding),可以直接访问对象的属性,或者给对象的属性赋值。黑魔法之一,很多高级的iOS开发技巧都是基于KVC实现的。 KVO 是键值观察者(key-value-observing)。实现方式:通过对某个对象的某个属性添加观察者,当该属性改变,就会调用”observeValueForKeyPath:”方法,为我们提供一个“对象值改变了!”的时机进行一些操作。
241 0
iOS开发:KVC与KVO
|
编译器 iOS开发
iOS-底层原理 23:KVO 底层原理
iOS-底层原理 23:KVO 底层原理
206 0
iOS-底层原理 23:KVO 底层原理
|
存储 搜索推荐 API
iOS-底层原理 22:KVC 底层原理
iOS-底层原理 22:KVC 底层原理
165 0
iOS-底层原理 22:KVC 底层原理
|
存储 API iOS开发
iOS底层原理:KVC分析(一)
KVC全称Key-Value Coding,俗称键值编码。它是一种通过字符串描述符而不是通过调用访问方法或者直接使用实例变量的非直接的访问对象属性的机制。在iOS中,NSObject、NSArray、NSDictionary等类使用这种机制并采用分类的形式为自身拓展了KVC的能力。
iOS底层原理:KVC分析(一)
|
安全 iOS开发
iOS探索 -- KVO 的原理分析
KVO (key-value-observing) 是一种 键值观察 机制, 它允许当前对象去观察目标对象的某个属性的变化; 当被观察对象的属性发生变化后, 会通过特定方法通知观察者对象属性变化的一些情况内容, 观察者对象拿到变化情况后做出相关操作。
187 0
|
网络协议 安全 API
iOS14适配汇总:【1、隐私权限相关:定位、相册、IDFA 2、KVC相关3、UIView相关;4、网络相关】
iOS14适配汇总:【1、隐私权限相关:定位、相册、IDFA 2、KVC相关3、UIView相关;4、网络相关】
506 0
iOS14适配汇总:【1、隐私权限相关:定位、相册、IDFA 2、KVC相关3、UIView相关;4、网络相关】
|
iOS开发
iOS底层原理:KVC分析(二)
简介: KVC全称Key-Value Coding,俗称键值编码。它是一种通过字符串描述符而不是通过调用访问方法或者直接使用实例变量的非直接的访问对象属性的机制。在iOS中,NSObject、NSArray、NSDictionary等类使用这种机制并采用分类的形式为自身拓展了KVC的能力。
|
iOS开发
IOS开发-KVC
kvc--key-value coding,健值编码 可以通过key直接访问对象属性的value的方法