В среде Cocoa имя метода доступа получается из символьной строки во время выполнения с помощью механизма, называемого доступом к значениям по ключам, или сокращенно KVC, где ключ — это символьная строка типа NSString с именем значения, к которому осуществляется доступ.

В основу механизма доступа к значениям по ключам положен неформальный протокол (по существу, категория) NSKeyValueCoding, которому соответствует класс NSObject, а следовательно, каждый объект. Тема доступа к значениям по ключам довольно обширна, и поэтому за дополнительными сведениями обращайтесь к документации Key-Value Coding Programming Guidet предоставляемой компанией Apple, где эта тема освещена наиболее полно.

К числу основных методов доступа к значениям по ключам относятся valueForKey: и setValue: f огКеу:. При вызове одного из этих методов для объекта осуществляется интроспекция этого объекта. Проще говоря, сначала находится подходящий селектор. Если он отсутствует, то доступ к переменной экземпляра осуществляется непосредственно.

Класс считается совместимым с механизмом доступа к значениям по заданному ключу, если он реализует методы или обладает переменной экземпляра для доступа по этому ключу. Всякая попытка получить доступ к ключу, для которого класс несовместим с доступом к значениям по ключам, приведет во время выполнения к исключению со следующим сообщением: “Этот класс несовместим с доступом к значениям по ключу имяКлюча”. (Последнее слово в этом сообщении об ошибке является символьной строкой, обозначающей, хотя и без кавычек, ключ, ставший причиной неисправности.) Допустим, что имеется следующий вызов метода доступа:

[myObject setValue: @"Hello" fогКеу:@"greeting"];

Сначала в этом вызове осуществляется поиск метода setGreeting: в классе myObject. Если этот метод существует, то он вызывается, и в качестве аргумента ему передается строковое значение @"Hello". При неудачном исходе вызова этого метода строковое значение @"Hello" присваивается непосредственно переменной экземпляра greeting (или ^greeting), если она присутствует в классе myObject. Если же и эта операция присваивания завершится неудачно, то генерируется исключение и выполнение приложения завершается аварийно.

 

Механизм доступа к значениям по ключам позволяет полностью обойти за-«му щищенность переменной экземпляра! Среде Cocoa известно, что вам как программисту это может и не понадобиться, поэтому в ней предоставляется метод класса accessInstanceVariablesDirectly, который можно переопределить таким образом, чтобы он возвращал логическое значение N0 вместо логического значения YES по умолчанию.

 

В качестве значения обоим методам, valueForKey: и setValue: fогКеу:, требуется объект. В сигнатуре метода доступа, а в его отсутствие — в самой переменной экземпляра, возможно, и нельзя использовать объект в качестве значения, и поэтому механизм доступа к значениям по ключам автоматически выполняет соответствующее преобразование. В частности, числовые типы данных, включая и B00L, выражаются в виде объекта типа NSNumber, а остальные типы данных (например, CGRect и CGPoint) — в виде объекта типа NSValue. Еще одной парой полезных методов являются dictionaryWithValuesForKeys: и setVal-uesForKeysWithDictionary:, которые позволяют получать и устанавливать многие пары “ключ-значение” средствами класса NSDictionary в одной команде.

По существу, механизм доступа к значениям по ключам позволяет во время выполнения решить, исходя из объекта типа NSString, какой именно метод доступа следует вызывать. Используя объект типа NSString вместо вызова метода доступа, можно обойтись без проверки на стадии компиляции на предмет отправляемого сообщения. Более того, механизму KVC ничего неизвестно о конкретном классе объекта, к которому происходит обращение. Так, можно послать сообщение valueForKey: любому объекту и успешно получить результат, при условии, что класс этого объекта совместим с механизмом KVC по заданному ключу. Это дает возможность обойтись без проверки во время компиляции на предмет объекта, которому посылается сообщение. Это довольно весомые преимущества механизма доступа к значениям по ключам, благодаря которым я сам часто пользуюсь этим механизмом.

Рассмотрим практический пример применения механизма доступа к значениям по ключам в прикладном коде. В моем приложении flashcard имеется класс Term, представляющий латинский термин, и в нем определено немало переменных экземпляра. На каждой карточке отображается один латинский термин, а значения переменных его экземпляра — в разных текстовых полях. Если пользователь коснется любого из трех текстовых полей, ему должен быть предоставлен интерфейс для перехода от текущего латинского термина к следующему термину, значение которого отличается от присутствующего в данном текстовом поле. Следовательно, прикладной код остается одним и тем же для всех трех текстовых полей. Единственное отличие заключается в выборе подходящей переменной экземпляра в поисках следующего термина для отображения. Безусловно, выразить такой параллелизм проще всего с помощью доступа к значениям по ключам, как показано ниже.

NSInteger tag = g.view.tag,

II переменная tag служит признаком выбранного текстового поля

NSString* key = nil;

switch (tag) (

case 1:   key         =             @"lesson"; break;

case 2:   key         =             0"lessonSection"; break;

case 3:   key         =             0"lessonSectionPartFirstWord";      break;

}

II получить текущее значение из соответствупцей переменной экземпляра

NSString* curValue = [[self currentC^rdController].term valueForKey: key];

II ...

Целый ряд встроенных классов Cocoa позволяет особым образом применять механизм доступа к значениям по ключам. Ниже приведены характерные тому примеры.

  • Если объекту класса NSArray посылается сообщение valueForKey:, он пересылает его каждому из своих элементов и возвращает новый массив, состоящий из полученных результатов, изящным и кратким (подобно дешевой карте) способом. Аналогичным образом ведет себя и класс NSSet.
  • В классе NSDictionary реализован метод valueForKey: в качестве альтернативы методу obj ectForKey: (он особенно полезен при наличии массива словарей типа NSArray). Аналогичным образом метод setValue: forKey: служит в классе NSMutableDictionary аналогом метода setObject: forKey:, за исключением того, что его параметр value: может принимать пустое значение nil. В этом случае вызывается метод removeObject: forKey:.
  • В классе NSSortDescriptor для сортировки массива типа NSArray каждому элементу этого массива посылается сообщение valueForKey:. Благодаря этому упрощается сортировка массива словарей по значению конкретного словарного ключа или массива объектов по значению конкретной переменной экземпляра.
  • Классы CALayer и CAAnimation позволяют применять механизм доступа к значениям по ключам для определения и извлечения значений произвольных ключей, как из словаря. Это удобно для присоединения данных идентификации и конфигурации к одному из экземпляров этих классов.
  • Класс NSManagedOb j ect, применяемый вместе с базой данных Core Data, гарантированно совместим с механизмом доступа к значениям по ключам для атрибутов, настраиваемых в модели сущностей. Следовательно, доступ к этим атрибутам обычно осуществляется с помощью методов valueForKey: и setValue: forKey:.

 

 

 

Добавить комментарий