KVC

        KVC(Key-value coding)键值编码,是一个基于NSKeyValueCoding非正式协议实现的机制,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值,而不需要调用明确的存取方法。这样就可以在运行时动态地访问和修改对象的属性,而不是在编译时确定。KVC是基于OC的动态特性和Runtime机制的。

NSObject(NSKeyValueCoding)

- (nullableid)valueForKey:(NSString*)key;//直接通过Key来取值

- (void)setValue:(nullableid)value forKey:(NSString*)key;//通过Key来设值

- (nullableid)valueForKeyPath:(NSString*)keyPath;//通过KeyPath来取值

- (void)setValue:(nullableid)value forKeyPath:(NSString*)keyPath;//通过KeyPath来设值

        KVC的定义都是对NSObject的扩展来实现的,OC中有个显式的NSKeyValueCoding类别名,所以对于所有继承了NSObject的类型,都能使用。

        实现了访问器方法的类中,使用点语法和KVC访问对象其实差别不大,二者可以任意混用。但是没有实现访问器方法的类中,点语法无法使用,这时KVC就有优势了。KVC 不但能够赋值,而且还能破坏只读的特性。OC中的KVC操作很暴力,这样做就会破坏类的封装性,类的私有属性和只读属性都可以通过KVC去访问。

        KVC支持嵌套。因为类key反复嵌套,所以有个keyPath的概念,keyPath就是用.语法把一个key链接起来,这样就可以根据这个路径访问下去(KVC在按照键值路径取值时,会自动层层深入,获取对应的键值)。

a.定义一个类

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@end

b.引用这个类

@interface OC_SWIFTViewController ()

@property (strong, nonatomic) Person *person;

@end

c.设置和获取

- (void)viewDidLoad {

    [super viewDidLoad];

    self.person= [[Person alloc] init];

    [self setValue:@"Jack" forKeyPath:@"person.name"];

     NSString*name = [self valueForKeyPath:@"person.name"];

     NSLog(@"%@",name);

}

d.输出结果

2019-11-27 17:46:15.643288+0800 OC-Swift[6346:274818] Jack

        如果开发者想让这个类禁用KVC里,那么重写+ (BOOL)accessInstanceVariablesDirectly方法让其返回NO即可,这样的话如果KVC没有找到set属性名时,会直接用setValue:forUndefinedKey:方法。valueForUndefinedKey:错误拦截,当key的值是没有定义的,这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来。

KVC要设值,那么就要找到对象中对应的key,KVC在内部是按什么样的顺序来寻找key的:

1.首先搜索 setter 方法,有就直接赋值。

2.如果上面的 setter 方法没有找到,再检查类方法+ (BOOL)accessInstanceVariablesDirectly

i.返回 NO,则执行setValue:forUNdefinedKey:

ii.返回 YES,则按_,_的顺序搜索成员名。

3.还没有找到的话,就调用setValue:forUndefinedKey:

你可能感兴趣的:(KVC)