21

NS(Mutable)Dictionariesでキーとして使用されるすべてのオブジェクトは、NSCopyingプロトコルをサポートする必要があり、それらのオブジェクトは、ディクショナリで使用されるときにコピーされます。

あるオブジェクトを別のオブジェクトにマップするために、より重いオブジェクトをキーとして使用したいことがよくあります。私がそれをするとき私が本当に意味することは効果的にです:

[dictionary setObject:someObject forKey:[NSValue valueWithPointer:keyObject]];

(「戻ってきて、この同じキーオブジェクトインスタンスをもう一度渡したら、同じ値を取得してください。」)

...これはまさに私が時々このデザインを回避するためにやることになることです。(はい、デスクトップCocoaのNSMapTableについては知っていますが、たとえばiPhoneはこれをサポートしていません。)

しかし、私が実際に得ていないのは、そもそもなぜキーをコピーすることが必要または望ましいのかということです。実装または呼び出し元は何を購入しますか?

4

3 に答える 3

26

コピーは、キーとして使用されている間、キーとして使用される値が「誤って」変更されないようにします。変更可能な文字列の例を考えてみましょう:

NSMutableString* key = ... 
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];

[dict setObject: ... forKey: key];

ディクショナリがキーをコピーせず、代わりにretain編集しただけであると仮定しましょう。後で元の文字列が変更された場合、まったく同じキー オブジェクト (つまりkey、上記の例)。

このような間違いから身を守るために、ディクショナリはすべてのキーをコピーします。

-copyWithZone:ところで、 を実行するだけと定義するのは簡単であることに注意してくださいreturn [self retain]。これは許可されており、オブジェクトが不変であり、NSCopying返されるオブジェクトが(ちょっと、ちょっと)不変でなければならないようにコントラクトが特別に設計されている場合に適したコードです。

クラスとそのコンテンツが不変の場合、新しいコピーを作成する代わりに元のコピーを保持することで、NSCopying を実装します。

( NSCopying リファレンスより)

「不変対可変」という考慮事項が受信オブジェクトに適用される場合、返されるコピーは不変です。それ以外の場合、コピーの正確な性質はクラスによって決定されます。

( -copyWithZone: リファレンスより)

オブジェクトが不変でない場合でも、ID ベースの等値/ハッシュ実装、つまりオブジェクトの内部状態によってまったく影響を受けない実装のみを使用する場合は、その実装で問題が解決する可能性があります。

于 2010-03-06T21:30:03.073 に答える
7

ポインタをキーとして保存したい場合は、. でNSValueオブジェクトにラップする必要があります+valueWithPointer:

于 2011-03-29T22:23:18.373 に答える
5

NSMapTableiOS 6 以降、ポインターをキーとして使用する場合は、オブジェクトを使用できます。http://nshipster.com/nshashtable-and-nsmaptable/を参照してください。

キーや値を強く保持するか弱く保持するかを指定できます。

NSMapTable *mapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory
                                         valueOptions:NSMapTableWeakMemory];

適切な場合がある別のオプションはNSCache、キーを強力に保持し、実際にはスレッドセーフである を使用することです。

于 2015-11-04T22:11:15.530 に答える