【原】iOS中KVC和KVO的区别

在iOS开发中经常会看到KVC和KVO这两个概念,比较可能混淆,特地区分一下

KVC(Key Value Coding)

 1> 概述

  KVC:Key Value Coding,键值编码,是一种间接访问实例变量的方法。

  KVC 提供了一个使用字符串(Key)而不是访问器方法,去访问一个对象实例变量的机制。

 2> KVC部分源码(头文件)

 1 // NSKeyValueCoding.h
 2 @interface NSObject(NSKeyValueCoding)
 3
 4 + (BOOL)accessInstanceVariablesDirectly;
 5
 6 - (nullable id)valueForKey:(NSString *)key;
 7 - (void)setValue:(nullable id)value forKey:(NSString *)key;
 8 - (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
 9
10 - (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
11
12 - (NSMutableOrderedSet *)mutableOrderedSetValueForKey:(NSString *)key NS_AVAILABLE(10_7, 5_0);
13
14 - (NSMutableSet *)mutableSetValueForKey:(NSString *)key;
15
16 - (nullable id)valueForKeyPath:(NSString *)keyPath;
17 - (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
18 - (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKeyPath:(NSString *)inKeyPath error:(out NSError **)outError;
19 - (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;
20 - (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath NS_AVAILABLE(10_7, 5_0);
21 - (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;
22
23 - (nullable id)valueForUndefinedKey:(NSString *)key;
24 - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
25 - (void)setNilValueForKey:(NSString *)key;
26 - (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
27 - (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
28
29 @end
30
31 @interface NSArray<ObjectType>(NSKeyValueCoding)
32
33 - (id)valueForKey:(NSString *)key;
34 - (void)setValue:(nullable id)value forKey:(NSString *)key;
35
36 @end
37
38 @interface NSDictionary<KeyType, ObjectType>(NSKeyValueCoding)
39
40 - (nullable ObjectType)valueForKey:(NSString *)key;
41
42 @end
43
44 @interface NSMutableDictionary<KeyType, ObjectType>(NSKeyValueCoding)
45
46 - (void)setValue:(nullable ObjectType)value forKey:(NSString *)key;
47
48 @end
49
50 @interface NSOrderedSet<ObjectType>(NSKeyValueCoding)
51
52 - (id)valueForKey:(NSString *)key NS_AVAILABLE(10_7, 5_0);
53 - (void)setValue:(nullable id)value forKey:(NSString *)key NS_AVAILABLE(10_7, 5_0);
54
55 @end
56
57 @interface NSSet<ObjectType>(NSKeyValueCoding)
58
59 - (id)valueForKey:(NSString *)key;
60 - (void)setValue:(nullable id)value forKey:(NSString *)key;
61
62 @end

  可以看到这个类里面包含了对类NSObject、NSArray、NSDictionary、NSMutableDictionary、NSOrderedSet、NSSet的扩展,扩展方法基本上为

- (id)valueForKey:(NSString *)key;
- (void)setValue:(nullable id)value forKey:(NSString *)key;

也就是说,基本上Objective-C里所有的对象都支持KVC操作,操作包含如上两类方法,动态读取和动态设值。

 3> 通过KVC键值编码访问属性

  ① key值查找

1 [stu setValue:@"xiaoqiang" forKey:@"name"];
2 [stu setValue:@"boy" forKey:@"gender"];
3 [stu setValue:@24 forKey:@"age"];
4
5 NSLog(@"name = %@, gender = %@, age = %@", [stu valueForKey:@"name"], [stu valueForKey:@"gender"], [stu valueForKey:@"age"]);

  ② 路径查找

1 Teacher *tea = [[Teacher alloc] init];
2 stu.teacher = tea;
3 [stu setValue:@"fangfang" forKeyPath:@"teacher.name"];
4
5 // 路径查找
6 NSLog(@"teacherName = %@", [stu valueForKeyPath:@"teacher.name"]);

  ③ 同时给多个属性赋值

 1 NSDictionary *dict = @{
 2                        @"name" : @"fangfang",
 3                        @"gender" : @"girl",
 4                        @"age" : @18,
 5                        @"hobby" : @"fangfang"
 6                        };
 7 Student *stu2 = [[Student alloc] init];
 8
 9 // 同时给多个属性赋值
10 [stu2 setValuesForKeysWithDictionary:dict];
11
12 NSLog(@"name = %@, gender = %@, age = %ld", stu2.name, stu2.gender, stu2.age);

 4> KVC抛出异常的方法

  ① 使用KVC设置值对象时

   如果当前类没有找到对象的Key值,系统会自动调用 setValue: forUndefinedKey: 方法

   该方法的默认实现是抛出一个异常,如果不想抛出异常,就重写这个方法

1 // 重写
2 // 使用KVC设置值对象
3 - (void)setValue:(id)value forUndefinedKey:(NSString *)key
4 {
5     NSLog(@"不存在Key:%@", key);
6 }

  ② 使用KVC取值的时候

     如果当前类没有找到对应的Key值,系统会自动调用 valueForUndefinedKey: 方法

     该方法的默认实现是抛出一个异常,如果不想抛出异常,就重写这个方法

1 // 重写
2 // 使用KVC取值的时候
3 - (id)valueForUndefinedKey:(NSString *)key
4 {
5     return nil;
6 }

 5> KVC的实现机制 

  KVC按顺序使用如下技术:

  • 检查是否存在getter方法-<key>或者setter方法-set<key>:的方法;
  • 如果没有上述方法,则检查是否存在名字为-_<key>、<key>的实例变量;
  • 如果仍未找到,则调用 valueForUndefinedKey: 和 setValue: forUndefinedKey: 方法。这些方法的默认实现都是抛出异常,我们可以根据需要重写它们。

KVO(Key Value Observer)

 1> 概述

  KVO:(Key Value Observer)键值观察者,是观察者设计模式的一种具体实现

  KVO触发机制:一个对象(观察者),监测另一对象(被观察者)的某属性是否发生变化,若被监测的属性发生的更改,会触发观察者的一个方法(方法名固定,类似代理方法)

 2> 一部分NSKeyValueObserving.h对于NSObject的拓展代码

 1 @interface NSObject(NSKeyValueObserving)
 2
 3 - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context;
 4
 5 @end
 6
 7 @interface NSObject(NSKeyValueObserverRegistration)
 8
 9 - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
10 - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context NS_AVAILABLE(10_7, 5_0);
11 - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
12
13 @end

  从拓展名称就可以看出,使用KVO需要注册监听器,也需要删除监听器。监听过程需要使用observeValueForKeyPath回调方法。

 3> 使用步骤

  注册观察者(为被观察者指定观察者以及被观察属性)

 1 // KVO 键值观察,是观察者设计模式
 2 @interface ViewController ()
 3
 4 // 观察可变数组的改变情况(苹果官方文档不建议对数组进行观察)
 5 @property (nonatomic, strong) NSMutableArray *array;
 6
 7 @end
 8
 9 - (void)viewDidLoad {
10     [super viewDidLoad];
11     // Do any additional setup after loading the view, typically from a nib.
12
13     self.array = [NSMutableArray array];
14
15     // 第一步:注册观察者
16     // 参数1:添加的观察者对象
17     // 参数2:字符串标识的key
18     // 参数3:触发添加观察者对象的时候
19     /*
20      NSKeyValueObservingOptionNew = 0x01 key或value只要有一个更新的时候就会触发
21      NSKeyValueObservingOptionOld = 0x02
22      NSKeyValueObservingOptionInitial = 0x04
23      NSKeyValueObservingOptionPrior = 0x08
24      */
25     // 参数4:文本内容 一般为nil
26     [self addObserver:self forKeyPath:@"array" options:NSKeyValueObservingOptionNew context:nil];
27 }

  ?实现回调方法

 1 // 第二步:实现回调
 2 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
 3 {
 4
 5     NSLog(@"keyPath = %@", keyPath);
 6     NSLog(@"object = %@", object);
 7     NSLog(@"change = %@", change);
 8
 9     // 可以进行刷新UI的操作
10 }

  触发回调方法(被观察属性发生更改)

 1 // 第二步:实现回调
 2 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
 3 {
 4
 5     NSLog(@"keyPath = %@", keyPath);
 6     NSLog(@"object = %@", object);
 7     NSLog(@"change = %@", change);
 8
 9     // 可以进行刷新UI的操作
10 }

  移除观察者

   在不需要观察者的时候需要把它删除,本人就只在视图将要消失时移除

1 // 视图将要消失的时候
2 - (void)viewWillDisappear:(BOOL)animated
3 {
4     // 在不需要观察者的时候需要把它删除
5     [self removeObserver:self forKeyPath:@"array"];
6 }
时间: 2024-08-21 05:37:14

【原】iOS中KVC和KVO的区别的相关文章

iOS 中KVC、KVO、NSNotification、delegate 总结及区别

iOS 中KVC.KVO.NSNotification.delegate 总结及区别 1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的关键技术之一. Demo: @interface myPerson : NSObject { NSString*_name; int      _age; int      _height; int      _w

iOS 中KVC、KVO、NSNotification、delegate 总结及区别-b

1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的关键技术之一. Demo: @interface myPerson : NSObject { NSString*_name; int      _age; int      _height; int      _weight; } @end @interface testViewController

【iOS】KVC 与 KVO

一.KVC与KVO *"KVC":key value Coding(键值编码) *目的:间接的修改或获取对象的属性,降低程序(类与类)之间的耦合度. *"KVO":key value Observer(键值观察),观察者模式.(检测模型变化用的多) *目的:通常用于观察某个对象的某个属性发生变化时,及时做出相应. 二.KVC的使用方式 KVC被称为iOS开发平台的大招!!! 能快速修改对象属性. *[p1setValue:@"xxxx"forKe

IOS中Retain和Copy的区别

IOS中Retain和Copy的区别 1 ,可读性: readonly  . readwrite@property(readwrite,....) valueType value;这个属性是变量的默认属性,就是如果你 (readwrite and readonly 都没有使用,那么你的变量就是 readwrite 属性 ) ,通过加入 readwrite 属性你的变量就会有 get 方法,和 set 方法.property(readonly,...) valueType value;这个属性变量

iOS开发中KVC、KVO简介

在iOS开发中,KVC和KVO是经常被用到的.可以使用KVC对对象的属性赋值和取得对象的属性值,可以使用KVO监听对象属性值的变化.简单介绍一下KVC和KVO. 一:键值编码(KVC) KVC,全称 Key Value Coding(键值编码),是OC 语言的一个特性,使用KVC,可以对对象的属性进行动态读写. KVC的操作方法由 NSKeyValueCoding协议提供,而NSObject已经实现了这个协议,因此OC中的几乎所有对象都可以使用KVC操作.常用的KVC操作方法有: (1)设置属性

[转] iOS (OC) 中 KVC 与 KVO 理解

转自: http://magicalboy.com/kvc_and_kvo/ KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性.KVO 就是基于 KVC 实现的关键技术之一. 一个对象拥有某些属性.比如说,一个 Person 对象有一个 name 和一个 address 属性.以 KV

iOS开发-KVC和KVO的理解

KVC和KVO看起来很专业,其实用起来还是比较简单的,KVC(Key-value coding)可以理解为键值对编码,如果对象的基本类型,那么键值对编码实际上和get,set方法没有区别,如果是属性是另外一个对象,那么发现KVC用起来还是非常顺手,KVO(key-value observing)是键值对的观察者模式,如果对象的属性发生变更,那么会触发observeValueForKeyPath事件,KVO的这种通知特性让我们在开发的时候节省了不必要的代码,提高了开发效率. KVC键值对编码 KV

【转载】iOS中delegate,notification,KVO三种模式实现通信的优缺点

原帖地址:http://blog.csdn.net/yangxt/article/details/8176636 在开发iOS中,有三种模式来实现controller之间的通信: 1.委托delegation: 2.通知中心Notification Center: 3.键值观察key value observing,KVO 因此,那为什么我们需要这些模式以及什么时候用它以及什么时候不用它. 1.delegate 基本特征: 一 个controller定义了一个协议(即一系列的方法定义).该协议描

Swift中KVC和KVO的使用

原创BLog,转载请注明出处 Swift中使用KVC和KVO的类都必须必须继承自NSObject KVC key-value coding 是一种间接访问对象的机制 key的值就是属性名称的字符串,返回的value是任意类型,需要自己转化为需要的类型 KVC主要就是两个方法 (1)通过key设置对应的属性 (2)通过key获取对应的属性 举例 class TestForKVC:NSObject{ var hwcCSDN = "hello world" } var instance =