1

NSMutableDictionaryインスタンスを別のキーとして使用したいNSMutableDictionary

    NSMutableDictionary *stuff = [NSMutableDictionary dictionary];
    NSMutableDictionary *first = [NSMutableDictionary dictionary];
    [stuff setObject:@"A" forKey:first];
    NSLog(@"I GOT %@",[stuff objectForKey:first]);

これにより、期待どおりに出力されます@"A"が、問題ありません。

ただし、後でfirstオブジェクト内の値を次のように変更すると、次のようになります。

[first setObject:@"C" forKey:@"Something"];

私は今得ることができません@"A"

NSLog(@"I GOT %@",[stuff objectForKey:first]);

どの出力nil

キーのメモリアドレスをディクショナリ内の既存のキーと比較すると仮定しobjectForKeyました。このようなメモリアドレスは、ディクショナリの内部値を変更しても変更されないため(私は思う)、機能すると思いました。

代わりにキーにsを使用することで、別のアプローチで動作させることができましNSStringた。文字列の値は、次のようにメモリアドレス自体になります。

    NSMutableDictionary *stuff = [NSMutableDictionary dictionary];
    NSMutableDictionary *first = [NSMutableDictionary dictionary];
    [stuff setObject:@"A" forKey:[NSString stringWithFormat:@"%p",first]];
    [first setObject:@"C" forKey:@"Something"];
    NSLog(@"I GOT %@",[NSString stringWithFormat:@"%p",first]);

どちらが機能しますか、印刷し@"A"ます。

私の質問:

  • 元のアプローチが機能しないのはなぜですか?
4

2 に答える 2

5

辞書は、設定されたときにそのキーのコピーを取得します(そのコピーは変更できません)。次に、キーに使用したオブジェクトを変更すると、そのオブジェクトとコピーは同等に比較されなくなります。つまり、キーのNSDictionary使用hashisEqual:チェックの際に使用されます。(コレクションは、これらのメソッドでオブジェクトのアドレスを使用して、それらが等しいかどうかを判断しません。等しい場合でも、コピーと元のアドレスは異なります。)したがって、値を取得することはできません。辞書を元の状態に再変更すると、検索は成功します。

あなたが思いついた文字列のトリックは良い回避策です。+[NSValue valueWithNonRetainedObject:]この目的にも使用できます。キーディクショナリのアドレスは、変更しただけでは変更されないため、後で検索するために同じ値を取得できます。

于 2013-02-21T18:34:49.770 に答える
2

objectForKeyは、キーのメモリアドレスをディクショナリ内の既存のキーと比較すると想定しました

複数のレベルで間違っています。

キーをメモリアドレスで比較した場合、キーのオブジェクトを取得するための現実的な方法はありません。定数文字列@"Foo"をキーとして使用し、実行時にNSStringコンテンツを含む別のインスタンスを渡しFooましたが、それは別のオブジェクトでした(したがって、そのメモリアドレスは完全に異なっていました)。

だからいいえ。objectForKey:代わりisEqual:に、キーにメッセージを送信して、キーが等しいかどうかを判断します。このメソッドは、デフォルトで実装されており、実際にメモリアドレスを比較しますが、それが適切なほとんどの標準コレクションクラス( 、、、、など)でNSObjectオーバーライドされ、意味的に正確なコンテンツ関連の比較を行います。 。NSStringNSNumberNSArrayNSDictionary

また、キーとオブジェクトのペアが設定されている場合、のキーNSDicionaryコピーされます。これは、直接ポインター比較が使用された場合、コピーは別のオブジェクトであり、ポインターが別の場所を指しているオブジェクトの別の実際のインスタンスであるため、オブジェクトを取得する方法がまったくないことを意味します(明らかに)。(補足:これは、のような一部の不変のCocoaクラスには完全には当てはまりませんNSString。ここで、copyは基本的にを使用して実装されretainますが、概念を理解する必要があります)。

于 2013-02-21T18:38:44.040 に答える