什么是KVC搜索模式mutableArrayValueForKey? [英] What is the KVC Search Pattern for mutableArrayValueForKey?

查看:2745
本文介绍了什么是KVC搜索模式mutableArrayValueForKey?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解Cocoa的键值编码(KVC)机制一点。我已阅读Apple的键值编程指南但是仍然有点困惑关于如何确定KVC方法搜索密钥。特别是 mutableArrayValueForKey:



下面我将解释我如何理解 valueForKey: KVCgetter工作。






有七种不同的getterKVC方法:

   - (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 docs声明 valueForKey:的搜索内容如下:


  1. Tries -getMyKey c>
  2. c $ c>, -myKey b $ b
  3. 如果没有找到,它会尝试这些有序,多对多的getter(NSArray):

      //必需:
    - (NSUInteger)countOfMyKey;

    //需要至少一个:
    - (id)objectInMyKeyAtIndex:(NSUInteger)index;
    - (NSArray *)myKeyAtIndexes:(NSIndexSet *)indexes;

    //可选(提高性能):
    - (void)getMyKey:(KeyClass **)buffer range:(NSRange)inRange;接下来,它尝试这些无序的,多对多的getter(NSSet):


       - (NSUInteger)countOfMyKey; 
    - (NSEnumerator *)enumeratorOfMyKey;
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject;


  4. 接下来,它尝试直接访问实例变量,假设 YES accessInstanceVariablesDirectly 以此顺序返回: _myKey _isMyKey myKey isMyKey


  5. 最后,它放弃并调用接收类的 - (id)valueForUndefinedKey:(NSString *)key 方法。通常在此处出现错误。







是什么是mutableArrayValueForKey的搜索顺序模式:?



苹果公司的文档声明了这一点:


订阅的访问器搜索模式
集合




mutableArrayValueForKey的默认搜索模式为
如下:



接收者的类被搜索一个
对的方法,其名称匹配
模式-insertObject:inAtIndex:
和-removeObjectFromAtIndex:
(分别对应于NSMutableArray
原始方法
insertObject:atIndex:和
removeObjectAtIndex:)或
方法匹配模式
-insert:atIndexes:和-removeAtIndexes:(对应于
NSMutableArrayinsertObjects:atIndexes:
和removeObjectsAtIndexes:方法)。
如果发现至少一个插入方法和
至少一个删除方法
每个NSMutableArray消息发送到
集合代理对象将
导致
-insertObject:inAtIndex :, -removeObjectFromAtIndex :, -insert:atIndexes :,和-removeAtIndexes:正在发送给
mutableArrayValueForKey:的原始接收者的消息。
... etc ...


这对我来说没有意义,因为它讨论了setter方法。 mutableArrayValueForKey:返回一个NSMutableArray。上面列出的所有方法返回void,并用于编辑NSMutableArray,而不是获取它。示例:

   - (void)insertMyKey:(KeyClass *)keyObject inMyKeyAtIndex:(NSUInteger) 
- (void)removeObjectFromMyKeyAtIndex:(NSUInteger)index;

任何想法苹果在他们的文档中说什么,或者这可能是一个错误? / p>

我的理论是 mutableArrayValueForKey:可能采取类似的路径 valueForKey: code>搜索以检索KVC值。我只是不确定是真正的路径。



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

解决方案

NSMutableArray $ c> mutableArrayValueForKey:实际上是 NSMutableArray 的私有子类,它覆盖了普通的数组方法,例如 -count -objectAtIndex: -insertObject:atIndex:等,并调用相应的KVC方法检索数组的对象。它基本上充当操作对象的多对多关系的代理,而不是你不必担心创建或返回自己。快速使用示例:

 播放列表* aPlaylist; 
Track * aTrack;
NSMutableArray * mutableTracks = [aPlaylist mutableArrayValueForKey:@tracks];
[mutableTracks insertObject:aTrack atIndex:0];

这段代码会在播放列表的开头添加一个曲目。如果Playlist类为其轨道关系实现了KVC方法,那么调用可变数组上的方法将导致在底层对象上调用适当的方法。所以在这个例子中,当你在数组上调用 insertObject:atIndex:时,数组将调用 insertObjectInTracks:atIndex:



现在,在这个例子中,当然你可以调用 insertObjectInTracks:atIndex:,但是有几个优点可以使用 mutableArrayValueForKey:




  • 数组封装器隐藏了底层KVC方法的实现细节。实现整个方法列表不是严格要求符合KVC。 Playlist类只能实现 -tracks -setTracks:,上面的代码仍然可以工作。在这种情况下,不是调用 insertObjectInTracks:atIndex:,可变数组代理将创建一个新的数组,在开头插入对象,然后调用 setTracks:。这显然效率较低,因此通常建议实施KVC方法的完整列表。

  • 在这种情况下,而不是键的常量字符串,而是有一个变量,使用 mutableArrayValueForKey:允许您操作关系,而不必知道必须调用的方法的确切名称。

  • 它还允许您使用任何方法 NSMutableArray / code>本身实现,所以例如你可以使用搜索数组的对象,排序数组等方法,而不必重写特殊的版本来处理KVC的东西。


I'm attempting to understand Cocoa's Key-Value Coding (KVC) mechanism a little better. I've read Apple's Key-Value Programming Guide but am still a little confused about how certain KVC methods search for keys. Particularly, mutableArrayValueForKey:.

Below I'm going to explain how I understand valueForKey: KVC "getters" to work. Then I'll get to my question regarding mutableArrayValueForKey.


There are seven different "getter" KVC methods:

- (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;

When searching for a Value inside a Property (named myKey), Apple's docs state that valueForKey: searches like this:

  1. Tries -getMyKey, -myKey, and -isMyKey (in that order) inside the receiver
  2. If not found, it attempts these ordered, to-many getters (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. Next, it attempts these unordered, to-many getters (NSSet):

    - (NSUInteger)countOfMyKey;
    - (NSEnumerator *)enumeratorOfMyKey;
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject;
    

  4. Next, it attempts to access Instance Variables directly, assuming YES is returned by accessInstanceVariablesDirectly, in this order: _myKey, _isMyKey, myKey, isMyKey.

  5. Lastly, it gives up and calls the receiving class's - (id)valueForUndefinedKey:(NSString *)key method. Usually an error is raised here.


My question is, what is the search order pattern for mutableArrayValueForKey:?

Apple's docs state this:

Accessor Search Pattern for Ordered Collections

The default search pattern for mutableArrayValueForKey: is as follows:

The receiver's class is searched for a pair of methods whose names match the patterns -insertObject:inAtIndex: and -removeObjectFromAtIndex: (corresponding to the NSMutableArray primitive methods insertObject:atIndex: and removeObjectAtIndex: respectively), or methods matching the pattern -insert:atIndexes: and -removeAtIndexes: (corresponding to the NSMutableArrayinsertObjects:atIndexes: and removeObjectsAtIndexes: methods). If at least one insertion method and at least one removal method are found each NSMutableArray message sent to the collection proxy object will result in some combination of -insertObject:inAtIndex:, -removeObjectFromAtIndex:, -insert:atIndexes:, and -removeAtIndexes: messages being sent to the original receiver of mutableArrayValueForKey:. ...etc...

This makes no sense to me as it's discussing "setter" like methods. mutableArrayValueForKey: returns an NSMutableArray. All of the methods listed above return void, and are used to edit an NSMutableArray, not get it. Example:

- (void)insertMyKey:(KeyClass *)keyObject inMyKeyAtIndex:(NSUInteger)index;
- (void)removeObjectFromMyKeyAtIndex:(NSUInteger)index;

Any idea what Apple is trying to say in their docs, or if this is perhaps an error?

My theory is that mutableArrayValueForKey: is likely taking a similar path as valueForKey: when searching to retrieve a KVC value. I'm just not sure what path that really is.

Thanks for any help you can offer! :)

解决方案

The NSMutableArray you get back from calling mutableArrayValueForKey: is actually a private subclass of NSMutableArray which overrides normal array methods such as -count, -objectAtIndex:, -insertObject:atIndex:, etc. and calls the corresponding KVC methods on the object the array was retrieved from. It basically acts as a proxy for manipulating the to-many relationship of the object, and it's not something you have to worry about creating or returning yourself. A quick example of usage:

Playlist* aPlaylist;
Track* aTrack;
NSMutableArray* mutableTracks = [aPlaylist mutableArrayValueForKey:@"tracks"];
[mutableTracks insertObject:aTrack atIndex:0];

This piece of code adds a track to the beginning of the playlist. If the Playlist class implements KVC methods for its "tracks" relationship, then calling a method on the mutable array will result in the appropriate method being called on the underlying object. So in this example, when you call insertObject:atIndex: on the array, the array will in turn call insertObjectInTracks:atIndex: on the playlist object, and the track gets added to the playlist's array of tracks.

Now, in this example, of course you could just call insertObjectInTracks:atIndex: directly, but there are several advantages you can get out of using mutableArrayValueForKey: instead.

  • The array wrapper hides the implementation details of the underlying KVC methods. Implementing the entire list of methods isn't strictly required to be KVC compliant. The Playlist class could just implement -tracks and -setTracks:, and the code above will still work. In this case, instead of calling insertObjectInTracks:atIndex:, the mutable array proxy will create a new array with the object inserted at the beginning, and then just call setTracks: on the Playlist object. This is obviously less efficient, so implementing the full list of KVC methods is usually recommended.
  • In the case where, instead of a constant string for the key, you instead have a variable, using mutableArrayValueForKey: allows you to manipulate the relationship without having to know the exact names of the methods you have to call. As long as the object is KVC compliant for the key you're using, everything will "just work".
  • It also lets you use any method that NSMutableArray itself implements, so for example you could use methods that search the array for objects, sort the array, etc. without having to rewrite special versions to deal with the KVC stuff.

这篇关于什么是KVC搜索模式mutableArrayValueForKey?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆