web-dev-qa-db-ja.com

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

このデータにアクセスできる唯一の方法は、最初に内部配列の内容をオブジェクトに設定することです。考え?

24
user455889

そのようなネストされたキーの場合、keyPathを使用できます。 keyPathは、ドットで結合された一連のキーです。それらを使用して、Key-Valueコーディングをサポートするオブジェクト(あなたのようなNSDictionaryオブジェクトを含む)からネストされた値を取得できます。したがって、あなたの場合、これはうまくいくはずです:

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

Key-Valueコーディングの詳細については、Appleの Key-Valueコーディングプログラミングガイド を参照してください。

この関連するStackOverflowの質問 も参照してください。

60
Simon Whitaker

Simon Whitakerの正解を使用して、辞書を辞書の辞書に埋め込むことで、定数の階層を構築することができました。以下は、私の実際のソースコードから変更されたサンプルソースコードです。

これは現実の問題解決です。私の特定のケースでは、目標は、iOS用のAppleのAppStoreでアプリ内購入のためにStoreKitを介してアクセスされる製品を識別する文字列を整理することでした。私たちのアプリが、1冊は猫、もう1冊は犬の2冊の本のコンテンツを表示するとします。さらに、私たちのアプリは、コンテンツの要約版と非要約版を販売しています。要約から非要約へのアップグレードは、3番目の製品である「アップグレード」を意味します。本の各ペアは、この場合は英語とイタリア語に翻訳される可能性があります。

私が追跡しようとしている弦を見ると、「なぜその男は、このKVCのナンセンスを通過するのではなく、弦自体を使用しないのですか?」と思うかもしれません。さて、2番目の文字列であるEnglish> Cats> Unabridgedに注目してください。文字列は、アンダースコアが追加されて終了します。これは、iTunesConnectを使用してアプリ内購入製品を作成したときに、誤ってそのアイテムを「非消耗品」ではなく「消耗品」として作成したためです。 Appleは、上記の製品を削除してもIDを変更できません。そのため、元の文字列を使用できませんでした。代わりに、回避策としてアンダースコアを追加しました。つまり、これらの文字列は恣意的で乱雑です。

このアプローチのもう1つの同様の必要性は、これらの文字列値がコンパイル時に時々変更される可能性があるため、ソースコード内の複数の場所にコピーして貼り付けたくない場合です。言い換えれば、定数の階層。

Xcode内で、これらの製品IDを参照するためのより良い方法が必要です。

// 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"] );
1
Basil Bourque
gfbPicture = [[[result objectForKey:@"metadata"] objectForKey:@"pictures"] objectForKey:@"picture"];
0
Matt Williamson