mutableArrayValueForKey的KVC搜索模式是什么?

时间:2010-02-19 01:08:55

标签: cocoa nsmutablearray key-value-coding

我试图更好地理解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:搜索如下:

  1. 在接收者中尝试-getMyKey-myKey-isMyKey(按此顺序)
  2. 如果没有找到,它会尝试这些有序的,多对多的吸气剂(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;
    
  3. 接下来,它尝试这些无序的,多对多的getter(NSSet):

    - (NSUInteger)countOfMyKey;
    - (NSEnumerator *)enumeratorOfMyKey;
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject;
    
  4. 接下来,它会尝试直接访问实例变量,假设YES返回accessInstanceVariablesDirectly,顺序为:_myKey_isMyKey,{{1 },myKey

  5. 最后,它放弃并调用接收类的isMyKey方法。通常会出现错误。


  6. 我的问题是,mutableArrayValueForKey的搜索顺序模式是什么:?

    Apple's docs state this

      

    订购的访问者搜索模式   集合

         

    默认搜索模式   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:类似的路径。我只是不确定究竟是什么路径。

    感谢您提供的任何帮助! :)

1 个答案:

答案 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:取而代之的优势。

  • 数组包装器隐藏了底层KVC方法的实现细节。实现整个方法列表并不严格要求符合KVC。播放列表类只能实现mutableArrayValueForKey:-tracks,上面的代码仍然可以使用。在这种情况下,不是调用-setTracks:,而是可变数组代理将创建一个新数组,并在开头插入对象,然后只调用播放列表对象上的insertObjectInTracks:atIndex:。这显然效率较低,因此通常建议实施完整的KVC方法列表。
  • 如果使用setTracks:代替键的常量字符串而不是变量,则使用mutableArrayValueForKey:可以操纵关系,而无需知道必须调用的方法的确切名称。只要该对象符合您正在使用的密钥的KVC,一切都将“正常工作”。
  • 它还允许您使用NSMutableArray本身实现的任何方法,例如,您可以使用在数组中搜索对象,对数组进行排序等的方法,而无需重写特殊版本来处理KVC东西。