本文共 4052 字,大约阅读时间需要 13 分钟。
原文地址:
KVC(Key-value coding)键值编码,单看这个名字可能不太好理解。其实翻译一下就很简单了,就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态在访问和修改对象的属性。而不是在编译时确定,这也是iOS开发中的黑魔法之一。很多高级的iOS开发技巧都是基于KVC实现的。目前网上关于KVC的文章在非常多,有的只是简单地说了下用法,有的讲得深入但是在使用场景和最佳实践没有说明,我写下这遍文章就是给大家详解一个最完整最详细的KVC。
KVC在iOS中的定义无论是Swift还是Objective-C,KVC的定义都是对NSObject的扩展来实现的(Objective-c中有个显式的NSKeyValueCoding类别名,而Swift没有,也不需要)所以对于所有继承了NSObject在类型,都能使用KVC(一些纯Swift类和结构体是不支持KVC的),下面是KVC最为重要的四个方法
当然NSKeyValueCoding类别中还有其他的一些方法,下面列举一些
KVC是怎么寻找Key的
KVC是怎么使用的,我相信绝大多数的开发者都很清楚,我在这里就不再写简单的使用KVC来设值和取值的代码了,首页我们来探讨KVC在内部是按什么样的顺序来寻找key的。
当调用setValue:属性值 forKey:@”name“的代码时,底层的执行机制如下:程序优先调用set:属性值方法,代码通过setter方法完成设置。注意,这里的是指成员变量名,首字母大清写要符合KVC的全名规则,下同
如果没有找到setName:方法,KVC机制会检查+ (BOOL)accessInstanceVariablesDirectly方法有没有返回YES,默认该方法会返回YES,如果你重写了该方法让其返回NO的话,那么在这一步KVC会执行setValue:forUNdefinedKey:方法,不过一般开发者不会这么做。所以KVC机制会搜索该类里面有没有名为的成员变量,无论该变量是在类接口部分定义,还是在类实现部分定义,也无论用了什么样的访问修饰符,只在存在以命名的变量,KVC都可以对该成员变量赋值。 如果该类即没有set:方法,也没有_成员变量,KVC机制会搜索is的成员变量, 和上面一样,如果该类即没有set:方法,也没有和_is成员变量,KVC机制再会继续搜索和is的成员变量。再给它们赋值。 如果上面列出的方法或者成员变量都不存在,系统将会执行该对象的setValue:forUNdefinedKey:方法,默认是抛出异常。 如果开发者想让这个类禁用KVC里,那么重写+ (BOOL)accessInstanceVariablesDirectly方法让其返回NO即可,这样的话如果KVC没有找到set:属性名时,会直接用setValue:forUNdefinedKey:方法。下面我们来让代码来测试一下上面的KVC机制
@interface Dog : NSObject
@end @implementation Dog { NSString* toSetName; NSString* isName; //NSString* name; NSString* _name; NSString* _isName; } // -(void)setName:(NSString)name{ // toSetName = name; // } //-(NSString)getName{ // return toSetName; //} +(BOOL)accessInstanceVariablesDirectly{ return NO; } -(id)valueForUndefinedKey:(NSString )key{ NSLog(@"出现异常,该key不存在%@",key); return nil; } -(void)setValue:(id)value forUndefinedKey:(NSString )key{ NSLog(@"出现异常,该key不存在%@",key); } @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... Dog dog = [Dog new]; [dog setValue:@"newName" forKey:@"name"]; NSString name = [dog valueForKey:@"toSetName"]; NSLog(@"%@",name); } return 0; }转载地址:http://fvfbm.baihongyu.com/