我试图更好地理解Cocoa的键值编码(KVC)机制。我已经阅读了Apple的Key-Value Programming Guide,但我仍然对某些KVC方法如何搜索密钥感到困惑。特别是, mutableArrayValueForKey:。
下面我将解释我如何理解valueForKey:
KVC“getters”的工作方式。然后我将讨论有关mutableArrayValueForKey的问题。
有七种不同的“getter”KVC方法:
- (id)valueForKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;
- (NSMutableSet *)mutableSetValueForKey:(NSString *)key;
- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;
在搜索属性中的值(名为 myKey )时,Apple的文档声明 valueForKey:搜索如下:
-getMyKey
,-myKey
和-isMyKey
(按此顺序)如果没有找到,它会尝试这些有序的,多对多的吸气剂(NSArray):
// Required:
- (NSUInteger)countOfMyKey;
// Requires At Least One:
- (id)objectInMyKeyAtIndex:(NSUInteger)index;
- (NSArray *)myKeyAtIndexes:(NSIndexSet *)indexes;
// Optional (improves performance):
- (void)getMyKey:(KeyClass **)buffer range:(NSRange)inRange;
接下来,它尝试这些无序的,多对多的getter(NSSet):
- (NSUInteger)countOfMyKey;
- (NSEnumerator *)enumeratorOfMyKey;
- (KeyClass *)memberOfMyKey:(KeyClass *)anObject;
接下来,它会尝试直接访问实例变量,假设YES
返回accessInstanceVariablesDirectly
,顺序为:_myKey
,_isMyKey
,{{1 },myKey
。
最后,它放弃并调用接收类的isMyKey
方法。通常会出现错误。
我的问题是,mutableArrayValueForKey的搜索顺序模式是什么:?
订购的访问者搜索模式 集合
默认搜索模式 mutableArrayValueForKey:as as 如下:
搜索接收者的类a 一对名称与之匹配的方法 patterns -insertObject:inAtIndex: 和-removeObjectFromAtIndex: (对应于NSMutableArray 原始方法 insertObject:atIndex:和 removeObjectAtIndex:分别),或 匹配模式的方法 -insert:atIndexes:和-removeAtIndexes :(对应于 NSMutableArrayinsertObjects:atIndexes: 和removeObjectsAtIndexes:方法)。 如果至少有一种插入方法和 找到至少一种去除方法 发送到每个NSMutableArray消息 集合代理对象将 导致某种组合 -insertObject:inAtIndex:, - removeFofAromIndex:, - insert:atIndexes:和-removeAtIndexes:消息被发送到原始接收者 mutableArrayValueForKey :. ...等等...
这对我来说毫无意义,因为它正在讨论“setter”之类的方法。 - (id)valueForUndefinedKey:(NSString *)key
返回NSMutableArray。上面列出的所有方法都返回void,用于编辑NSMutableArray,而不是获取它。例如:
mutableArrayValueForKey:
知道Apple试图在他们的文档中说些什么,或者这可能是错误吗?
我的理论是- (void)insertMyKey:(KeyClass *)keyObject inMyKeyAtIndex:(NSUInteger)index;
- (void)removeObjectFromMyKeyAtIndex:(NSUInteger)index;
在搜索KVC值时可能采用与mutableArrayValueForKey:
类似的路径。我只是不确定究竟是什么路径。
感谢您提供的任何帮助! :)
答案 0 :(得分:21)
您从调用NSMutableArray
返回的mutableArrayValueForKey:
实际上是NSMutableArray
的私有子类,它会覆盖正常数组方法,例如-count
,-objectAtIndex:
,{ {1}}等,并在从中检索数组的对象上调用相应的KVC方法。它基本上充当了操纵对象的多对多关系的代理,并且你不必担心创建或返回自己。一个快速使用示例:
-insertObject:atIndex:
这段代码将曲目添加到播放列表的开头。如果Playlist类为其“track”关系实现KVC方法,则在可变数组上调用方法将导致在底层对象上调用适当的方法。因此,在此示例中,当您在数组上调用Playlist* aPlaylist;
Track* aTrack;
NSMutableArray* mutableTracks = [aPlaylist mutableArrayValueForKey:@"tracks"];
[mutableTracks insertObject:aTrack atIndex:0];
时,数组将依次调用播放列表对象上的insertObject:atIndex:
,并将轨道添加到播放列表的轨道数组中。
现在,在此示例中,您当然可以直接致电insertObjectInTracks:atIndex:
,但您可以使用insertObjectInTracks:atIndex:
取而代之的优势。
mutableArrayValueForKey:
和-tracks
,上面的代码仍然可以使用。在这种情况下,不是调用-setTracks:
,而是可变数组代理将创建一个新数组,并在开头插入对象,然后只调用播放列表对象上的insertObjectInTracks:atIndex:
。这显然效率较低,因此通常建议实施完整的KVC方法列表。setTracks:
代替键的常量字符串而不是变量,则使用mutableArrayValueForKey:
可以操纵关系,而无需知道必须调用的方法的确切名称。只要该对象符合您正在使用的密钥的KVC,一切都将“正常工作”。NSMutableArray
本身实现的任何方法,例如,您可以使用在数组中搜索对象,对数组进行排序等的方法,而无需重写特殊版本来处理KVC东西。