KVC使用与实现原理
2019-04-14 本文已影响9人
Lxin_
KVC介绍
KVC是Key Value Coding的简称。它是一种可以通过字符串的名字(对象中属性的名称)(key)来访问类属性的机制,而不是通过调用Setter、Getter方法访问。KVC的方法定义在Foundation/NSKeyValueCoding中。
KVC用法
- setValue: forKey:(为对象的属性赋值)
- setValue: forKeyPath:(为对象的属性赋值(包含了setValue:forKey:的功能,并且还可以对对象内的类的属性进行赋值))
- valueForKey:(根据key取值)
- valueForKeyPath:(根据keyPath取值)
- setValuesForKeysWithDictionary:(对模型进行一次性赋值)
赋值的使用及实现步骤
Person.h
#import <Foundation/Foundation.h>
interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end
Person.m
#import "Person.h"
@implementation Person
- (void)setName:(NSString *)name {
NSLog(@"setName:");
}
- (void)_setName:(NSString *)name {
NSLog(@"_setName:");
}
- (void)setIsName:(NSString *)name {
NSLog(@"setIsName:");
}
+ (BOOL)accessInstanceVariablesDirectly {
NSLog(@"accessInstanceVariablesDirectly");
return YES;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
NSLog(@"setValue: forUndefinedKey:");
}
- (void)setNilValueForKey:(NSString *)key {
NSLog(@"setNilValueForKey:");
}
@end
ViewController.m
#import "ViewController.h"
#import "Person.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *person = [[Person alloc] init];
[person setValue:@"Alex" forKey:@"name"];
}
@end
当通过注释@property (nonatomic, copy) NSString *name;
依次注释Person.m文件中各方法,Person.h中添加Person类的成员属性_name、_isName、name、isName
@interface Person : NSObject {
NSString *_name;
NSString *_isName;
NSString *name;
NSString *isName;
}
以及依次注释4个成员属性,得出如下结论。
[person setValue:@"Alex" forKey:@"name"]
- 先去找Person类的
setName:
方法,如果有,通过setName:
方法来设置属性 - 如果没有
setName:
方法,再依次找_setName:
、setIsName:
方法设置属性 - 如果无上述setter方法,查找
+ (BOOL)accessInstanceVariablesDirectly
方法(默认已实现,返回Yes),如果为Yes,继续往下执行,否则执行6。 - 分别查找成员变量
_name
、_isName
、name
、isName
,如果存在,赋值。 - 如果上述都不存在,调用
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
方法,如果这个方法没有重写,直接崩溃。
取值的使用及实现步骤
[person valueForKey:@"name"];
- 首先按
getName
,name
,isName
的顺序查找getter方法,找到直接调用。如果是BOOL、int等内建值类型,会做NSNumber的转换。 - 上面的getter没找到,查找
countOfKey
、objectInKeyAtindex
、KeyAtindexes
格式的方法。如果countOfKey和另外两个方法中的一个找到,那么就会返回一个可以响应NSArray所有方法的代理集合的NSArray消息方法。 - 还没找到,查找
countOfKey
、enumeratorOfKey
、memberOfKey
格式的方法。如果这三个方法都找到,那么就返回一个可以响应NSSet所有方法的代理集合。 - 还是没找到,如果类方法
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
返回YES。那么按_key
,_isKey
,key
,iskey
的顺序搜索成员名。 - 再没找到,调用
valueForUndefinedKey
,如果这个方法没有重写,则直接崩溃。