Класс 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 в приведенном ниже фрагменте кода.

[[NSUserDefaults standardUserDefaults] registerDefaults:

[NSDictionary dictionaryWithObjectsAndKeys:

@4,

@"cardMatrixRows",

@3,

@"cardMatrixColumns", nil]];

Этот код можно переписать следующим образом:

[[NSUserDefaults standardUserDefaults] registerDefaults:

@)@"cardMatrixRows": @4, 0"cardMatrixColumns":03}];

Для того чтобы извлечь значение из словаря по заданному ключу, вместо вызова метода obj ectForKey: теперь можно просто указать индекс ключа в квадратных скобках для ссылка на словарь следующим образом: diet [key]. Аналогично для ввода пары “ключ-значение” в словарь типа NSMutableDictionary вместо вызова метода setObject: forKey: эту пару можно просто присвоить ссылке на проиндексированный словарь. Как и в классе NSArray, все это делается подспудно с помощью вызываемых методов objectForKeyedSubscript: и setObject: f orKeyedSubscript:. Эти методы достаточно объявить в своих классах, чтобы сделать последние пригодными для обозначения индексирования по ключу.

Такие структуры данных, как массив словарей, словарь словарей и т.д., весьма распространены и нередко лежат в основе функциональных возможностей приложения. Рассмотрим пример, взятый из одного из моих приложений. Пакет приложения содержит текстовый файл со следующим содержимым:

chapterNumber [tab] pictureName [return]

chapterNumber [tab] pictureName [return]

При запуске моего приложения этот текстовый файл загружается и подвергается синтаксическому анализу, в результате которого составляется словарь. Каждая статья этого словаря имеет следующую структуру:

key: (chapterNumber, as an NSNumber)

value: [Mutable Array]

(pictureName)

(pictureName)

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

Ниже приведен конкретный код для синтаксического анализа текстового файла, в результате чего составляется подобная структура данных. Для каждой строки из текстового файла в словаре создается статья, если она не существует под номером данной главы, а в качестве значения служит пустой изменяемый массив. Как бы то ни было, статья теперь существует в словаре, а ее значением является изменяемый массив, к которому присоединяется название

иллюстрации. Обратите внимание, каким образом в данном простом примере совместно используются многие классы из каркаса Foundation, обсуждаемые в этом разделе.

NSString* f = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"txt"]; NSError* err = nil;

NSString* s = [NSString stringWithContentsOfFile:f

encoding:NSUTF8StringEncoding error:&err];

// проверка ошибок опущена

NSMutableDictionary* d = [NSMutableDictionary new];

for (NSString* line in [s componentsSeparatedByString:@"\n"]) {

NSArray* items = [line componentsSeparatedByString:@"\t"];

NSInteger chnum = [items[0] integerValue];

NSNumber* key = @(chnum);

NSMutableArray* marr = d[key];

if (!marr) { // такой ключ отсутствует, создать пару "ключ-значение" marr = [NSMutableArray new] ; d[key] = marr;

// теперь массив marr является изменяемым, пустым или заполненным NSString* picname = items[1];

[marr addObject: picname];

}

Из словаря типа NSDictionary можно получить список ключей, отсортированный список ключей или список значений. Обойти (перечислить) статьи словаря можно по его ключам, используя конструкцию for. . .in, хотя порядок такого обхода, разумеется, не определен. Кроме того, словарь предоставляет метод objectEnumerator, который можно использовать в конструкции for. . .in для обхода только значений. Имеется также возможность обойти пары “ключ-значение”, используя блок, и даже отфильтровать словарь типа NSDictionary, проверяя его значения.

 

Переход на современный язык Objective-C

Если у вас имеется устаревший прикладной код, который требуется преобразовать, чтобы воспользоваться синтаксисом литералов NSNumber, NSArray и NSDictionary языка Objective-C, а также индексированием массивов и словарей, вы можете сделать это без всякого труда. С этой целью выберите команду меню Edit^RefactorOConvert to Modern Objective-C Syntax.


 

 

 

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