tl;dr:
CFDictionaryRef提供されたデフォルトのコールバック関数を使用して を作成します。それはあなたが望むことをします。とは呼ばないでくださいNSDictionary。
はい、CFDictionaryRefキーを保持し、コピーしない を作成できます。実際、これは のデフォルトの動作ですCFDictionaryRef。
のドキュメントにCFDictionaryCreateMutable()は次のように書かれています:
ディクショナリに CFType オブジェクトのみが含まれる場合は、ポインタをkCFTypeDictionaryKeyCallBacksこのパラメータとして渡し、デフォルトのコールバック関数を使用します。
(したがって、通常のObjective-Cオブジェクトのみを配列に入れ、void *ポインターなどのランダムなものを入れない場合、これが必要です)
そして、ドキュメントにkCFTypeDictionaryKeyCallBacksは次のように書かれています:
CFDictionaryKeyCallBacksCFDictionary のキーがすべて CFType 派生オブジェクトである場合に使用するのに適した一連のコールバックを含む定義済みの構造体。保持コールバックはCFRetain、解放コールバックはCFRelease、コピー コールバックはCFCopyDescription、等価コールバックはCFEqualです。したがって、ディクショナリの作成時にこの定数へのポインタを使用すると、キーはコレクションに追加されると自動的に保持され、コレクションから削除されると解放されます。
retainコールバックは(実際には存在しない)CFRetain()のようなものではないことに注意してください。CFCopyObject
実際、Core Foundation には「任意のオブジェクトをコピーする」標準的な方法がありません。そのためCFStringCreateCopy、CFArrayCreateCopy、CGPathCreateCopy、 などの関数が存在します。
したがって、できることは、次のように辞書を作成することです。
CFDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
これで、キーを保持し、コピーしないディクショナリが作成されました。
私が言おうとしていることを理解していただけるように、次の部分を大きな文字で書きます。
あなたが作成したこの辞書はNSDictionary.
はい、無料NSDictionaryでCFDictionaryRefブリッジされています。ただし、これCFDictionaryRefを にキャストすると、ドキュメントの次NSDictionaryの行のため、そのブリッジングの悪用になります。NSDictionary
...キーは任意のオブジェクトにすることができます(NSCopyingプロトコルに準拠している場合-以下を参照)
同様に、ドキュメントには-[NSMutableDictionary setObject:forKey:]明示的に次のように記載されています。
キーがコピーされます ( を使用しcopyWithZone:ます。キーは NSCopying プロトコルに準拠している必要があります)。
ディクショナリのキーは に準拠する必要<NSCopying>はなく、 を使用してコピーされません。-copyWithZone:つまり、ディクショナリはNSDictionary(またはNSMutableDictionary) ではありません。コードで使用されている場合NSDictionaryは常に、キーがコピーされる(保持されない) キーと値のマップを提供する必要があります。それが API コントラクトです。それ以外のことを行うと、未定義の動作が発生する可能性があります。
(一部のオブジェクトが にオーバーライド-copyするという事実return [self retain]は実装の詳細であり、「 とは何か」に関するこの説明には関係ありませんNSDictionary。)