Что такое шаблон поиска KVC для mutableArrayValueForKey? - PullRequest
16 голосов
/ 19 февраля 2010

Я пытаюсь немного лучше понять механизм кодирования ключа-значения (KVC) Какао.Я прочитал Apple Key-Value Programming Guide , но все еще немного озадачен тем, как определенные методы KVC ищут ключи.В частности, mutableArrayValueForKey: .

Ниже я собираюсь объяснить, как я понимаю, valueForKey: KVC "геттеры" работают.Затем я перейду к моему вопросу, касающемуся mutableArrayValueForKey.


Существует семь различных методов 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. Затем он пытается этинеупорядоченные методы получения ко-многим (NSSet):

    - (NSUInteger)countOfMyKey;
    - (NSEnumerator *)enumeratorOfMyKey;
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject;
    
  4. Затем он пытается получить прямой доступ к переменным экземпляра, предполагая, что YES возвращается accessInstanceVariablesDirectly в следующем порядке:_myKey, _isMyKey, myKey, isMyKey.

  5. Наконец, он сдается и вызывает метод - (id)valueForUndefinedKey:(NSString *)key принимающего класса.Обычно здесь возникает ошибка.


Мой вопрос: каков шаблон порядка поиска для mutableArrayValueForKey:?

Документы Apple утверждают это :

Шаблон поиска средства доступа для упорядоченных коллекций

Шаблон поиска по умолчанию для mutableArrayValueForKey: выглядит следующим образом:

Класс получателявыполняется поиск пары методов, имена которых соответствуют шаблонам -insertObject: inAtIndex: и -removeObjectFromAtIndex: (соответствует примитивным методам NSMutableArray: insertObject: atIndex: и removeObjectAtIndex: соответственно) или методам, соответствующим шаблону -insert: atIndexes: - иremoveAtIndexes: (соответствует NSMutableArrayinsertObjects: atIndexes: и removeObjectsAtIndexes: методы).Если найден хотя бы один метод вставки и хотя бы один метод удаления, каждое сообщение NSMutableArray, отправленное объекту-посреднику коллекции, приведет к некоторой комбинации -insertObject: inAtIndex :, -removeObjectFromAtIndex :, -insert: atIndexes :, и -removeAtIndexes: messagesотправляется исходному получателю mutableArrayValueForKey :.... и т.д ...

Это не имеет смысла для меня, так как здесь обсуждаются методы, подобные "сеттерам".mutableArrayValueForKey: возвращает NSMutableArray.Все перечисленные выше методы возвращают void и используются для редактирования NSMutableArray, а не для его получения.Пример:

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

Любая идея, что Apple пытается сказать в своих документах, или, возможно, это ошибка?

Моя теория состоит в том, что mutableArrayValueForKey:, вероятно, идет по тому же пути.как valueForKey: при поиске для получения значения KVC.Я просто не уверен, какой путь это действительно.

Спасибо за любую помощь, которую вы можете предложить!:)

1 Ответ

21 голосов
/ 19 февраля 2010

NSMutableArray, который вы получаете от вызова mutableArrayValueForKey:, фактически является частным подклассом NSMutableArray, который переопределяет обычные методы массива, такие как -count, -objectAtIndex:, -insertObject:atIndex: и т. Д., И вызывает соответствующий KVC методы объекта, из которого был получен массив. По сути, он действует как прокси для манипулирования отношениями объекта со многими, и вам не нужно беспокоиться о том, чтобы создать или вернуть себя. Быстрый пример использования:

Playlist* 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: для объекта Playlist. Это, очевидно, менее эффективно, поэтому обычно рекомендуется использовать полный список методов KVC.
  • В случае, когда вместо постоянной строки для ключа вместо вас есть переменная, использование mutableArrayValueForKey: позволяет вам манипулировать отношениями без необходимости знать точные имена методов, которые вы должны вызывать. Пока объект соответствует KVC для ключа, который вы используете, все будет "просто работать".
  • Он также позволяет вам использовать любой метод, который реализует NSMutableArray, так что, например, вы можете использовать методы, которые ищут в массиве объекты, сортируют массив и т. Д. Без необходимости переписывать специальные версии для работы с KVC.
...