25

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

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

4

3 回答 3

62

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

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

有关键值编码的更多详细信息,请参阅 Apple 的键值编码编程指南

另请参阅这个相关的 StackOverflow 问题

于 2010-11-30T19:50:13.233 回答
1

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

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

看着我试图跟踪的字符串,你可能会想“为什么那个人不直接使用字符串而不是经历这个 KVC 废话?”。好吧,注意第二个字符串,English > Cats > Unabridged。字符串以附加的下划线结尾。那是因为当我使用 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"] );
于 2013-11-16T06:04:48.607 回答
0
gfbPicture = [[[result objectForKey:@"metadata"] objectForKey:@"pictures"] objectForKey:@"picture"];
于 2010-11-30T19:42:44.897 回答