您的位置:首页 > 移动开发 > Objective-C

iOS开发--Objective-C之KVC

2015-06-14 22:07 555 查看
首先来了解一下什么KVC,KVC就是我们平时所说的键值编码,简单的理解就是可以通过一个key值,修改对象的与这个key对应属性的值,也可以根据该key获取对象的与这个key相对应属性的值。

KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:

设置属性的值:

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

参数说明:value:想要设置的值, key:键值

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

参数说明:value:想要设置的值, keyPath:键值路径

这个两个方法有什么区别呢?

setValue: forKey:只能修改对象的直接属性,不能修改对象间接属性(对象属性的属性值),setValue: forKeyPath:可以修改间接属性的值,当然也可以修改直接属性的值。

换言之,setValue: forKey:只支持单级映射,而setValue: forKeyPath:支持多级映射。

获取属性的值:

- (id)valueForKey:(NSString *)key; // 只能获取对象的直接属性,

- (id)valueForKeyPath:(NSString *)keyPath; // 可获取对象的间接属性

说明:通过KVC的方式不仅对对象的共有属性(在.h文件声明的属性)有效,对私有属性(在.m文件声明的属性)也有效。

下面通过代码来进一步认识KVC

Dog类

Dog.h

@interface Dog : NSObject
// 公有属性
@property (nonatomic, copy) NSString *name; // 狗的名字

@end</span>



Dog.m

@interface Dog ()
// 私有属性
@property (nonatomic, assign) CGFloat weight;// 狗的重量

@end




Person类

Person.h

@interface Person : NSObject
// 公有属性
@property (nonatomic, copy) NSString *phoneNum; // 人的身高
@property (nonatomic, strong) Dog *dog; // 人有一条狗

@end


Person.m

@interface Person()
// 私有属性
@property (nonatomic, assign) int age; // 人的年龄

@end


#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {

Person *p = [[Person alloc] init];

// 通过KVC方式 修改一个对象的成员属性,
[p setValue:@"10086" forKey:@"phoneNum"];
[p setValue:@(26) forKey:@"age"]; // 私有成员属性

//通过KVC方式 访问一个对象的成员属性
NSString *pPhoneNum = [p valueForKey:@"phoneNum"];
int pAge = [[p valueForKey:@"age"] intValue];  // 私有成员属性
NSLog(@"pPhoneNum = %@,  pAge = %d", pPhoneNum, pAge);

// 可以通过KVC修改和访问一个对象的属性的属性 (多级映射)
Dog *d = [[Dog alloc] init];
p.dog = d;

[p setValue:@"HaQiDog" forKeyPath:@"p.dog.name"];
[p setValue:@(10.7) forKeyPath:@"p.dog.weight"]; // 私有成员属性

NSString *dName = [p valueForKeyPath:@"p.dog.name"];
CGFloat dWeight = [[p valueForKeyPath:@"p.dog.weight"] floatValue]; // 私有成员属性

NSLog(@"dName = %@, dWeight = %f", dName, dWeight);
}
return 0;
}


那KVO内部到底是如何实现的呢?

设置属性,优先查找属性的set方法,如果没有该方法则优先考虑搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的setValue:forUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确设置);

读取属性,优先查找属性的get方法,如果没有搜索到则会优先搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的valueforUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确读取);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: