2

キーをコピーする代わりに保持する NSMutableDictionary を作成する方法を見つけようとしています。-(NSUInteger)hash と -(id)isEqual を実装しました。目的のキーに対して、コールバックで指定するオプションを特定するのに苦労しています。

CFDictionaryKeyCallBacks    keyCallbacks    = { 0, NULL, NULL, CFCopyDescription, CFEqual, NULL };


self.commonParents = (NSMutableDictionary*)CFBridgingRelease(CFDictionaryCreateMutable(nil, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks));

上記のコードは、キーへの弱い参照を使用する場合に ARC で正しく機能しますが、強い参照が必要な場合はどうすればよいでしょうか? 主要なコールバックはどのように見えるべきですか?

4

4 に答える 4

5

tl;dr:

CFDictionaryRef提供されたデフォルトのコールバック関数を使用して を作成します。それはあなたが望むことをします。とは呼ばないでくださいNSDictionary


はい、CFDictionaryRefキーを保持し、コピーしない を作成できます。実際、これは のデフォルトの動作ですCFDictionaryRef

のドキュメントにCFDictionaryCreateMutable()は次のように書かれています:

ディクショナリに CFType オブジェクトのみが含まれる場合は、ポインタをkCFTypeDictionaryKeyCallBacksこのパラメータとして渡し、デフォルトのコールバック関数を使用します。

(したがって、通常のObjective-Cオブジェクトのみを配列に入れ、void *ポインターなどのランダムなものを入れない場合、これが必要です)

そして、ドキュメントにkCFTypeDictionaryKeyCallBacksは次のように書かれています:

CFDictionaryKeyCallBacksCFDictionary のキーがすべて CFType 派生オブジェクトである場合に使用するのに適した一連のコールバックを含む定義済みの構造体。保持コールバックはCFRetain、解放コールバックはCFRelease、コピー コールバックはCFCopyDescription、等価コールバックはCFEqualです。したがって、ディクショナリの作成時にこの定数へのポインタを使用すると、キーはコレクションに追加されると自動的に保持され、コレクションから削除されると解放されます。

retainコールバックは(実際には存在しない)CFRetain()のようなものではないことに注意してください。CFCopyObject

実際、Core Foundation には「任意のオブジェクトをコピーする」標準的な方法がありません。そのためCFStringCreateCopyCFArrayCreateCopyCGPathCreateCopy、 などの関数が存在します。

したがって、できることは、次のように辞書を作成することです。

CFDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

これで、キーを保持し、コピーしないディクショナリが作成されました。

私が言おうとしていることを理解していただけるように、次の部分を大きな文字で書きます。

あなたが作成したこの辞書はNSDictionary.

はい、無料NSDictionaryCFDictionaryRefブリッジされています。ただし、これCFDictionaryRefを にキャストすると、ドキュメントの次NSDictionaryの行のため、そのブリッジングの悪用になります。NSDictionary

...キーは任意のオブジェクトにすることができます(NSCopyingプロトコルに準拠している場合-以下を参照)

同様に、ドキュメントには-[NSMutableDictionary setObject:forKey:]明示的に次のように記載されています。

キーがコピーされます ( を使用しcopyWithZone:ます。キーは NSCopying プロトコルに準拠している必要があります)。

ディクショナリのキーは に準拠する必要<NSCopying>はなく、 を使用してコピーされません。-copyWithZone:つまり、ディクショナリはNSDictionary(またはNSMutableDictionary) ではありません。コードで使用されている場合NSDictionaryは常に、キーがコピーされる(保持されない) キーと値のマップを提供する必要があります。それが API コントラクトです。それ以外のことを行うと、未定義の動作が発生する可能性があります。

(一部のオブジェクトが にオーバーライド-copyするという事実return [self retain]は実装の詳細であり、「 とは何か」に関するこの説明には関係ありませんNSDictionary。)

于 2013-02-24T20:39:20.263 に答える
1

最良の答えはコメントに埋もれていると思うので、ここで強調し+[NSMapTable strongToStrongObjectsMapTable]ますweak

于 2014-12-21T18:52:27.177 に答える
0

普通の古い NSMutableDictionary を使用して達成できる解決策は 2 つあります。それらは NSMapTable ほどエレガントではありません。
各キーには があるuniqueIDと述べているので、この値は時間の経過とともに変化しないと思います。

オプション 1 :実際のキーを
使用して、uniqueIDNSArray を格納する NSMutableDictionary のキーにすると、@[key, value]構造全体が次のようになります。
@{ key1.uniqueID : @[key1, value1], key2.uniqueID : @[key2 : value2] }

オプション 2 :
オプション 1 のラッパーである NSObject のサブクラスを作成します。またはオプション 1 の任意のバリエーション。

それらはuniqueID変更されない場合にのみ有効です

于 2013-02-24T19:55:40.690 に答える
0

これを行う代わりに、NSStringまたはキーとして使用しているクラスをサブクラス化し、コピーされた文字列ではなく保持された文字列を返すようにコピーメソッドをオーバーライドすることをお勧めします。

于 2013-02-24T18:21:13.760 に答える