Прямой доступ к значениям вложенного словаря в Objective-C
Есть ли способ прямого доступа к внутреннему массиву внешнего массива в Objective-C? Например, вызов внешнего источника данных возвращает следующий объект:
{
bio = "this is the profile.bio data";
"first_name" = John;
"last_name" = Doe;
location = {
name = "Any Town, Any State";
};
metadata = {
pictures = {
picture = "https://picture.mysite.com/picture.jpeg";
}
}
}
Я хочу иметь доступ, например, к имени location.name или metadata.pictures.picture. Точечная нотация, однако, не работает. Например:
_gfbLocation = [result objectForKey:@"location.name"];
_gfbPicture = [result objectForKey:@"metadata.pictures.picture"];
Единственный способ получить доступ к этим данным - сначала установить содержимое внутренних массивов на объекты. Мысли?
Ответы
Ответ 1
Для таких вложенных ключей вы можете использовать keyPath. KeyPath - это всего лишь серия ключей, соединенных с точками. Вы можете использовать их для извлечения вложенных значений из объектов, поддерживающих Key-Value Coding, включая объекты NSDictionary, подобные вашим. Поэтому в вашем случае это должно работать:
[result valueForKeyPath:@"location.name"];
Подробнее о кодировании с ключом см. в Apple Руководство по программированию кодирования по ключевым словам.
См. также fooobar.com/questions/255863/....
Ответ 2
Используя правильный ответ Симона Уитакера, я смог построить иерархию констант, введя словарь в словарь в словаре. Ниже приведен пример исходного кода, измененного из моего реального исходного кода.
Это реальное проблемное решение. В моем конкретном случае целью была организация строк, которые идентифицируют продукты, доступные через StoreKit для покупки в приложении в Apple App Store для iOS. Представьте, что наше приложение представляет контент из пары книг, один на кошек, других собак. Кроме того, наше приложение продает сокращенную версию контента, а также сокращает. Модернизация от сокращенного до неограниченного означает третий продукт, "обновление". Каждая пара книг может быть переведена, в данном случае на английский и итальянский.
Глядя на строки, которые я пытаюсь отслеживать, вы можете подумать: "Почему этот парень просто не использует сами струны, а не переживает эту бессмысленность KVC?". Ну, обратите внимание на вторую строку, английский > Кошки > Unabridged. Строка заканчивается добавленным подчеркиванием. Это потому, что, когда я использовал iTunesConnect для создания продуктов In-App Purchase, я случайно создал этот элемент как "Расходуемый" вместо "Non-Consumable". Apple не позволяет изменять идентификатор, даже если вы удалите упомянутый продукт. Поэтому исходная строка не может быть использована; В качестве альтернативы я добавил подчеркивание в качестве обходного пути. Итак, дело в том, что эти строки являются произвольными и беспорядочными.
Еще одна подобная потребность в этом подходе заключалась бы в том, что, если эти значения строк могут время от времени меняться во время компиляции, вы не захотите вставлять копии в несколько мест в исходном коде. Иерархия констант, другими словами.
Внутри Xcode я хочу получить лучший способ обращения к этим идентификаторам продуктов.
// Using new literals syntax in later versions of Xcode 4 (& 5) to declare and populate a dictionary nested in a dictionary also in a dictionary.
NSDictionary *productIdentifiersHierarchy = @{
@"en" : @{
@"cats" : @{
@"abridged" : @"com.example.My_App.cats_abridged_en",
@"unabridged" : @"com.example.My_App.cats_unabridged_en_",
@"upgrade" : @"com.example.My_App.cats_upgrade_en"
},
@"dogs" : @{
@"abridged" : @"com.example.My_App.dogs_abridged_en",
@"unabridged" : @"com.example.My_App.dogs_unabridged_en",
@"upgrade" : @"com.example.My_App.dogs_upgrade_en"
}
},
@"it" : @{
@"cats" : @{
@"abridged" : @"com.example.My_App.cats_abridged_it",
@"unabridged" : @"com.example.My_App.cats_unabridged_it",
@"upgrade" : @"com.example.My_App.cats_upgrade_it"
},
@"dogs" : @{
@"abridged" : @"com.example.My_App.dogs_abridged_it",
@"unabridged" : @"com.example.My_App.dogs_unabridged_it",
@"upgrade" : @"com.example.My_App.dogs_upgrade_it"
}
}
};
Здесь, как получить доступ к этим тройным вложенным словарям.
// Use KVC (Key-Value Coding) as a convenient way to access the nested dictionary structure.
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.upgrade"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.upgrade"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.upgrade"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.abridged"] );
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.unabridged"] );
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.upgrade"] );
Ответ 3
gfbPicture = [[[result objectForKey:@"metadata"] objectForKey:@"pictures"] objectForKey:@"picture"];