直接访问Objective-C中的嵌套字典值

时间:2010-11-30 19:39:30

标签: iphone objective-c dictionary nsdictionary key-value-coding

有没有办法在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"];

我能够访问此数据的唯一方法是首先将内部数组的内容设置为对象。想法?

3 个答案:

答案 0 :(得分:60)

对于这样的嵌套键,您可以使用 keyPath 。 keyPath只是一系列用点连接的键。您可以使用它们从支持键值编码的对象中检索嵌套值 - 包括像您这样的NSDictionary对象。所以在你的情况下,这应该有效:

[result valueForKeyPath:@"location.name"];

有关键值编码的更多详细信息,请参阅Apple的Key-Value Coding Programming Guide

另见this related StackOverflow question

答案 1 :(得分:1)

使用Simon Whitaker的正确答案,我能够通过在Dictionary中的Dictionary中嵌入Dictionary来构建常量层次结构。以下是从我的真实源代码修改的示例源代码。

这是一个现实世界的问题解决方案。在我的特定情况下,目标是组织字符串,以识别通过StoreKit在Apple的App Store for iOS中进行应用程序内购买的产品。想象一下,我们的应用程序提供了一对书中的内容,一本关于猫,另一本关于狗。此外,我们的应用程序销售内容的删节版本以及未删节内容。从简化升级到未删节意味着第三种产品“升级”。每本书都可能被翻译,在这种情况下是英语和意大利语。

看着我试图追踪的字符串,你可能会想“为什么那个人不只是使用字符串而不是通过这个KVC废话?”。好吧,注意第二个字符串,英语>猫>未删节。该字符串以附加的下划线结尾。那是因为当我使用iTunesConnect创建应用程序内购买产品时,我意外地将该项目创建为“耗材”而不是“非耗材”。 Apple即使您删除了该产品,也不允许更改ID。所以不能使用原始字符串;或者,我附加了下划线作为解决方法。所以重点是,这些字符串是任意和混乱的。

这种方法的另一个类似需求是,如果这些字符串值偶尔会在编译时发生变化,那么您不希望将复制粘贴到源代码中的多个位置。换句话说,常量的层次结构。

在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"] );

答案 2 :(得分:0)

gfbPicture = [[[result objectForKey:@"metadata"] objectForKey:@"pictures"] objectForKey:@"picture"];