Класс NSDictionary представляет неупорядоченную коллекцию пар “ключ-значение”, которые в некоторых языках программирования называются просто хешем. Ключ обычно, хотя и не обязательно, является объектом типа NSString.
Значение может быть любым объектом. Класс NSDictionary является неизменяемым, тогда как его подкласс NSMutableDictionary — изменяемым.
Ключи словаря являются раздельными и сравниваются методом isEqual:. Если попытаться ввести пару “ключ-значение” в словарь типа NSMutableDictionary, то эта пара будет введена, при условии, что указанный ключ отсутствует в словаре. Если он уже присутствует в словаре, то соответствующее значение заменяется указанным.
Класс NSDictionary применяется в основном для запроса значения из статьи словаря по заданному ключу (с помощью метода objectForKey:). Если такой ключ отсутствует в словаре, то в результате получается значение nil, а следовательно, это еще один способ выяснить наличие ключа в словаре. Таким образом, словарь является простым и удобным средством для хранения данных и объектно-ориентированным аналогом структуры. Словари нередко применяются в среде Cocoa для предоставления дополнительного набора именованных значений. Примерами тому служат свойство userlnfo класса NSNotification, параметр options: метода application: didFinishLaunchingWithOptions : и т.д.
Те же самые усовершенствования Objective-C, благодаря которым стали доступны для программирования литералы массивов и индексирование, сделали возможным применение литералов словарей и аналогичное индексирование. Словарь
можно сформировать не только из массива объектов и массива ключей (с помощью метода dictionaryWithOb jects: f orKeys:) или списка чередующихся объектов и ключей с завершающим значением nil (с помощью метода dictionaryWithObjectsAndKeys:), но и непосредственно в виде списка разделяемых запятой пар “ключ-значение”, где после каждого ключа следует двоеточие и значение, а весь этот список заключается в выражение 0 {...}. Итак, вернемся к рассмотренному ранее примеру применения класса NSUserDefaults в приведенном ниже фрагменте кода.
Для того чтобы извлечь значение из словаря по заданному ключу, вместо вызова метода obj ectForKey: теперь можно просто указать индекс ключа в квадратных скобках для ссылка на словарь следующим образом: diet [key]. Аналогично для ввода пары “ключ-значение” в словарь типа NSMutableDictionary вместо вызова метода setObject: forKey: эту пару можно просто присвоить ссылке на проиндексированный словарь. Как и в классе NSArray, все это делается подспудно с помощью вызываемых методов objectForKeyedSubscript: и setObject: f orKeyedSubscript:. Эти методы достаточно объявить в своих классах, чтобы сделать последние пригодными для обозначения индексирования по ключу.
Такие структуры данных, как массив словарей, словарь словарей и т.д., весьма распространены и нередко лежат в основе функциональных возможностей приложения. Рассмотрим пример, взятый из одного из моих приложений. Пакет приложения содержит текстовый файл со следующим содержимым:
При запуске моего приложения этот текстовый файл загружается и подвергается синтаксическому анализу, в результате которого составляется словарь. Каждая статья этого словаря имеет следующую структуру:
В конечном итоге все иллюстрации к главе собираются под одним номером этой главы. Такая структура данных предназначена для того, чтобы значительно упростить и ускорить последующий доступ ко всем иллюстрациям к данной главе.
Ниже приведен конкретный код для синтаксического анализа текстового файла, в результате чего составляется подобная структура данных. Для каждой строки из текстового файла в словаре создается статья, если она не существует под номером данной главы, а в качестве значения служит пустой изменяемый массив. Как бы то ни было, статья теперь существует в словаре, а ее значением является изменяемый массив, к которому присоединяется название
иллюстрации. Обратите внимание, каким образом в данном простом примере совместно используются многие классы из каркаса Foundation, обсуждаемые в этом разделе.
Из словаря типа NSDictionary можно получить список ключей, отсортированный список ключей или список значений. Обойти (перечислить) статьи словаря можно по его ключам, используя конструкцию for. . .in, хотя порядок такого обхода, разумеется, не определен. Кроме того, словарь предоставляет метод objectEnumerator, который можно использовать в конструкции for. . .in для обхода только значений. Имеется также возможность обойти пары “ключ-значение”, используя блок, и даже отфильтровать словарь типа NSDictionary, проверяя его значения.
Переход на современный язык Objective-C
Если у вас имеется устаревший прикладной код, который требуется преобразовать, чтобы воспользоваться синтаксисом литералов NSNumber, NSArray и NSDictionary языка Objective-C, а также индексированием массивов и словарей, вы можете сделать это без всякого труда. С этой целью выберите команду меню Edit^RefactorOConvert to Modern Objective-C Syntax.