本文参考博客http://blog.youkuaiyun.com/ajrm0925/article/details/7484678,未尽之处可到原博客中查找
一、KVC的原理
KVC运用了一个isa-swizzling技术,并且通过isa-swizzling来实现其内部查找定位的。简单讲 ,在编译时KVC会被进行如下编译:
//编译前
[obj setValue:@"objName" forKey:@"name"]
//编译后
SEL sel = sel_get_uid ("setValue:forKey:");
IMP method = objc_msg_lookup (obj->isa,sel);
method(obj, sel, @"objName", @"name");
上面的三个方法可以理解为
1. 用sel_get_uid方法,通过字符串获得方法的指针
2. 用objc_msg_lookup方法,用isa指针到对象所属的类中,通过方法指针找到方法
3. 调用方法赋值
二、KVC的应用
1. 重写setValue:forKey
在字典转模型中,如果字典中的key有id这个关键字,直接转模型时会报警告,为了解决这个警告,我们可以重写setValue:forKey:
- (void)setValue:(id)value forKey:(NSString *)key
{
if ([key isEqualToString:@"id"]) {
[self setValue:value forKeyPath:@"ID"];
}else{
[super setValue:value forKey:key];
}
}
2. 基本的赋值取值
[book setValue:@"《乔布斯传》" forKey:@"name"];
NSString *name=[book valueForKey:@"name"];
3. 使用路径
可以通过点语法取值
@interface Author : NSObject {
NSString *name;
}
@end
#import "Author.h"
@implementation Author
@end
@class Author;
@interface Book : NSObject {
NSString *name;
Author *author;
}
@end
Book *book=[[[Book alloc] init] autorelease];
[book setValue:@"《乔布斯传》" forKey:@"name"];
NSString *name=[book valueForKey:@"name"];
Author *author=[[[Author alloc] init] autorelease];
[author setValue:@"Walter Isaacson" forKey:@"name"];
[book setValue:author forKey:@"author"];
NSString *authorName=[book valueForKeyPath:@"author.name"];
4. 自动装箱拆箱
即可以用基本数据类型接收传入的字符串类型,也可以用字符串类型直接打印取出来的基本数据类型。
5. 对数组的操作
Book *book =[[[Book alloc] init] autorelease];
Book *book1=[[[Book alloc] init] autorelease];
[book1 setValue:@"5.0" forKey:@"price"];
Book *book2=[[[Book alloc] init] autorelease];
[book2 setValue:@"4.0" forKey:@"price"];
NSArray *books=[NSArray arrayWithObjects:book1,book2,nil];
[book setValue:books forKey:@"relativeBooks"];
NSLog(@"relative books price: %@",[book valueForKeyPath:@"relativeBooks.price"]);
6. 为实例的多个属性赋值
Book *book4=[[Book alloc] init];
NSArray *bookProperties=[NSArray arrayWithObjects:@"name",@"price",nil];
NSDictionary *bookPropertiesDictionary=[book4 dictionaryWithValuesForKeys:bookProperties];
NSLog(@"book values: %@",bookPropertiesDictionary);
NSDictionary *newBookPropertiesDictionary=[NSDictionary dictionaryWithObjectsAndKeys:@"《Objective C入门》",@"name", @"20.5",@"price",nil];
[book4 setValuesForKeysWithDictionary:newBookPropertiesDictionary];
NSLog(@"book with new values: %@",[book4 dictionaryWithValuesForKeys:bookProperties]);