KVC (Key-Value Coding)

(Key-Value Coding) AND KVO ( Key-Value Observing) 在面试中时常被问到,一开始我也很模糊,现在简单的介绍下这两种机制。(我翻译的有错误,我写下来,只是为了自己看一遍能多记住点)

一. KVC

NSKeyValueCoding informal protocol , 可以让你直接通过 name (or key)访问一个对象的属性,而不用调用一个访问方法去访问。Key-value coding 是key-value observing, Cocoa bindings, Core Data, 等的基础。Accessor method 包括了(getter 和 setter),不仅支持对象,也支持标量(int 之类)和结构体。

Keys and Key Paths: key 一定要是ASCII编码,以小写字母开头,不能包含空格(虽然建议用小写开头,但是也是支持大写开头的,比如URL)。Key Paths: 比如 , address.street,首先可以访问address的属性,然后再访问address的street属性。

Getting Values :valueForKey得到属性值,如果不能得到属性的值会发送valueForUndefinedKey:可以通过重写首先方法处理 NSUndefinedKeyException 异常。dictionaryWithValuesForKeys 返回key array 中所有key对应的value。

Setting Values: 调用 setValues:forKey:如果没有找到对应的Key,则调用 setValue:forUndefineKey:,发出NSUndefinedKeyException异常

dot(.) 表达符跟 KVC: 你可以使用 key-value coding 不管是否使用 dot(.) 表达式,同样你也可以使用dot(.)不管是否用了KVC。

你可以使用 key-value coding 去获得一个属性。例如

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. @interface MyClass  
  2. @property NSString *stringProperty;  
  3. @property NSInteger integerProperty;  
  4. @property MyClass *linkedInstance;  
  5. @end  
使用KVC keyPath
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. MyClass *myInstance = [[MyClass alloc] init];  
  2. NSString *string = [myInstance valueForKey:@"stringProperty"];  
  3. [myInstance setValue:@2 forKey:@"integerProperty"];  

不是用 keyPath,而是使用 dot(.)符号

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. MyClass *anotherInstance = [[MyClass alloc] init];  
  2. myInstance.linkedInstance = anotherInstance;  
  3. myInstance.linkedInstance.integerProperty = 2;  

KVO 访问方法:(注意key 与 Key 的区别》

一个key的标准化的访问方法是 -<key>,返回相应的数据。对一个BOOL类型的属性,可以用 -is<Key>来替代。例如BOOL 类型的 hidden。

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. - (BOOL)hidden {  
  2.    // Implementation specific code.  
  3.    return ...;  
  4. }  
  5. 替代方法(BOOL)类型  
  6. - (BOOL)isHidden {  
  7.    // Implementation specific code.  
  8.    return ...;  
  9. }  

而设置访问方法(setValue:forKey:),则是 -set<Key>

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. (void)setHidden:(BOOL)flag {  
  2.   // Implementation specific code.  
  3.   return;  

加入不是对象类型的属性,一定要实现传递是 nil 的情况。当你将一个属性设置为nil时候,KVC方法 setNilValueForKey会被调用。比如你设置hidden(同上,BOOL类型)为nil时候 ,他会生产一个 BOOL 值的 NSNumber 对象,调用 setValue:forKey: 例如

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. - (void)setNilValueForKey:(NSString *)theKey {  
  2.    
  3.     if ([theKey isEqualToString:@"hidden"]) {  
  4.         [self setValue:@YES forKey:@"hidden"];  
  5.     }  
  6.     else {  
  7.         [super setNilValueForKey:theKey];  
  8.     }  
  9. }  

setValue:forKey: 默认的搜索模式:

1.首先会去搜索方法,set<Key>

2.假如没有找到set<Key>, accessInstanceVariablesDirectly 返回 YES,然后再按照 _<key>, _is<Key>, <key>, is<Key>顺序执行。

 3.如果还是没有找到,则 调用 -setValue:forUndefineKey:

valueForKey: 默认的搜索模式:

1.先按照 get<Key>, <key>, is<Key>, 假如返回的类型是一个对象,那么指向这个对象的指针直接返回。如果返回值是标量(scalar type), 假如支持 NSNumber 的转换,则返回NSNumber,否则返回NSValue(不仅仅是 NSPoint, NSSize, NSRect, NSRang)

2.如果上面的没有执行,则countOf<Key>,objectIn<Key>AtIndex: <key>AtIndexes:(对应与NSArray)

3.countOf<Key>, enumeratorOf<Key>,memberOf<Key>: (对应NSSet)

4.假如没有找到set<Key>, accessInstanceVariablesDirectly 返回 YES,然后再按照 _<key>, _is<Key>, <key>, is<Key>顺序执行。 假如返回的类型是一个对象,那么指向这个对象的指针直接返回。如果返回值是标量(scalar type), 假如支持 NSNumber 的转换,则返回NSNumber,否则返回NSValue(不仅仅是 NSPoint, NSSize, NSRect, NSRang)

5.如果还是没有找到,则 调用 -valueForUndefineKey:



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值