6

2 つの NSDictionaries をマージしようとしています。

NSDictionary *areaAttributes = [[area entity] attributesByName];
NSDictionary *gpsAttributes = [[gps entity] attributesByName];
NSMutableDictionary *combinedAttributes = [areaAttributes mutableCopy];
[combinedAttributes addEntriesFromDictionary:gpsAttributes];

しかし、次のエラーが発生します。

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: 'The key 'latitude' is not defined for this NSKnownKeysDictionary'

latitudeは鍵ですgpsAttributes

4

1 に答える 1

11

NSKnownKeysDictionaryここでの問題は、通常の辞書ではなく、AppleがCocoaのさまざまな部分で使用している文書化されていないタイプであるを扱っていることです。

SDKからObjCクラス情報をダンプする場合、またはそれが怖すぎる場合は、他の人のバージョンを読んでください。これは実際にはのサブクラスであるNSMutableDictionaryだけNSDictionaryでなく、すでに変更可能であるため、mutableCopy必要ありません。

さらに重要なことに、プロトコルNSCopyingNSMutableCopyingプロトコルがどのように定義されているかを読んだ場合mutableCopy、基本クラスと可変互換性のあるものを返す必要はありません。それが可変であり、その基本クラスと不変に互換性があるということだけです。これは迷惑です。

ここでの答えは、新しい可変ディクショナリを生成し、両方の NSKnownKeysDictionaryオブジェクトからその中にキーをコピーすることです。

NSDictionary *areaAttributes = [[area entity] attributesByName];
NSDictionary *gpsAttributes = [[gps entity] attributesByName];
NSMutableDictionary *combinedAttributes = [NSMutableDictionary dictionaryWithCapacity:20];
[combinedAttributes addEntriesFromDictionary:areaAttributes];
[combinedAttributes addEntriesFromDictionary:gpsAttributes];

(明らかに、パフォーマンスが心配な場合は、それを微調整するか20、各辞書からキーの数を取得して合計を渡します。ただし、通常は問題ではありません。)

なぜAppleがこれをしたのか不思議に思うかもしれません。しかし、あなたがそれについて考えるならば、それは便利なものです。structいくつかのライブラリの内臓内でCのように使用できるオブジェクトがありますが、外観は.のように見えNSDictionaryます。(たとえば、Pythonの場合と同様の目的namedtupleです。)それらを返すメソッドはすべてNSDictionary、ではなくを返すように設計されNSMutableDictionaryているため、キーのセットが制限されていることを誰も知りません。もちろん、彼らが呼び出す場合を除いてmutableCopy

また、これを事前にどのように知ることができるのか疑問に思われるかもしれません。まあ、あなたは本当にできません。オブジェクトのタイプをログに記録するか、例外ハンドラーを作成して例外をログに記録するか、クラッシュさせてクラッシュダンプで例外を見つけます。または、代わりに、あなたは防御的であり、どんな辞書もあなたに役に立たないことを与えることができると仮定することができますmutableCopy-あなたがコントロールするタイプの辞書にそれをコピーしてください。

于 2013-01-15T21:55:09.960 に答える