一. 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 去获得一个属性。例如
- @interface MyClass
- @property NSString *stringProperty;
- @property NSInteger integerProperty;
- @property MyClass *linkedInstance;
- @end
- MyClass *myInstance = [[MyClass alloc] init];
- NSString *string = [myInstance valueForKey:@"stringProperty"];
- [myInstance setValue:@2 forKey:@"integerProperty"];
不是用 keyPath,而是使用 dot(.)符号
- MyClass *anotherInstance = [[MyClass alloc] init];
- myInstance.linkedInstance = anotherInstance;
- myInstance.linkedInstance.integerProperty = 2;
KVO 访问方法:(注意key 与 Key 的区别》
一个key的标准化的访问方法是 -<key>,返回相应的数据。对一个BOOL类型的属性,可以用 -is<Key>来替代。例如BOOL 类型的 hidden。
- - (BOOL)hidden {
- // Implementation specific code.
- return ...;
- }
- 替代方法(BOOL)类型
- - (BOOL)isHidden {
- // Implementation specific code.
- return ...;
- }
而设置访问方法(setValue:forKey:),则是 -set<Key>
- (void)setHidden:(BOOL)flag {
- // Implementation specific code.
- return;
加入不是对象类型的属性,一定要实现传递是 nil 的情况。当你将一个属性设置为nil时候,KVC方法 setNilValueForKey会被调用。比如你设置hidden(同上,BOOL类型)为nil时候 ,他会生产一个 BOOL 值的 NSNumber 对象,调用 setValue:forKey: 例如
- - (void)setNilValueForKey:(NSString *)theKey {
- if ([theKey isEqualToString:@"hidden"]) {
- [self setValue:@YES forKey:@"hidden"];
- }
- else {
- [super setNilValueForKey:theKey];
- }
- }
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: