2010-11-30 14 views
20

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

このデータにアクセスできる唯一の方法は、まず内部配列の内容をオブジェクトに設定することです。思考?あなたはキーパスを使用することができますように、ネストされたキーについては

+3

ちなみに、これらのキー/値のデータ構造は配列と呼ばれますが、Objective-C用語では辞書(特にNSDictionaryオブジェクト)と呼ばれます。もしあなたがあなたの質問に言い換えると、他の人がそれを(そして答え)より簡単に見つけるのに役立ちます。たとえば、ネストされたNSDictionary値に直接アクセスするというタイトルを提案したいと思います。ありがとう! –

答えて

55

。 keyPathは、ドットで結合された一連のキーです。それらを使用して、あなたのようなNSDictionaryオブジェクトを含むKey-Value Codingをサポートするオブジェクトからネストされた値を取り出すことができます。だからあなたの場合には、この作業をする必要があります:キー値コーディングの詳細については

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

を、AppleのKey-Value Coding Programming Guideを参照してください。

this related StackOverflow questionも参照してください。

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

いいえ、valueForKeyPathを使用します。 (上記のSimonの回答を参照してください) – jsd

+0

これは非常に役に立ちます –

+0

keypathの値を使用します。サイモンの答えを確認してください –

1

私はSimon Whitakerの正解を使用して、ディクショナリをディクショナリに埋め込むことで定数の階層を構築することができました。以下は私の実際のソースコードから変更されたソースコードの例です。

これは実際の問題解決の方法です。私の特別なケースでは、目標は、App StoreでApp StoreでiOS用App Storeでアクセスした商品を識別する文字列を整理することでした。私たちのアプリが一対の本、猫、他の犬からのコンテンツを提示するとします。さらに、私たちのアプリはコンテンツの要約版と無制限版を販売しています。要約から未導入へのアップグレードは、第3の製品「アップグレード」を意味します。各ペアの書籍は、この場合英語とイタリア語で翻訳される可能性があります。

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

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

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

ありがとう、バジル。質問。どのように 'NSLog(@"%@ "、stuff)'を実行せずにNSLogを実行できますか? ?? –

+1

NSLog(オブジェクト)を呼び出すと、[オブジェクトの説明]文字列が自動的にシーンの後ろに呼び出されます。 – Neimsz

関連する問題