所有在 NS(Mutable)Dictionaries 中用作键的对象都必须支持 NSCopying 协议(protocol),并且这些对象在字典中使用时会被复制。
我经常想使用较重的对象作为键,只是将一个对象映射到另一个对象。当我这样做时,我真正的意思是有效:
[dictionary setObject:someObject forKey:[NSValue valueWithPointer:keyObject]];
(“当我回来并再次向您提供相同的关键对象实例时,请为我提供相同的值。”)
...这正是我有时为了解决这个设计而最终所做的事情。 (是的,我知道桌面 Cocoa 中的 NSMapTable;但例如 iPhone 不支持此。)
但是我真正不明白的是为什么复制 key 首先是必要的或可取的。它为实现或调用者买了什么?
最佳答案
该副本确保用作键的值在用作键时不会“暗中”更改。考虑可变字符串的示例:
NSMutableString* key = ...
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject: ... forKey: key];
假设字典没有复制 key ,而只是保留
它。如果现在,在稍后的某个时刻,原始字符串被修改,那么即使您使用完全相同的键对象(即一个 ),您也很可能不会再次在字典中找到存储的值。 key
指向上面示例中的位置)。
为了保护自己免受此类错误的影响,字典会复制所有键。
顺便说一句,请注意,将 -copyWithZone:
定义为 return [self keep]
非常简单。如果你的对象是不可变的,那么这是允许的,并且是好的代码,并且 NSCopying 合约是专门设计的,使得返回的对象必须(有点,有点)不可变:
Implement NSCopying by retaining the original instead of creating a new copy when the class and its contents are immutable.
(来自 NSCopying Reference )
和
The copy returned is immutable if the consideration “immutable vs. mutable” applies to the receiving object; otherwise the exact nature of the copy is determined by the class.
(来自 -copyWithZone: Reference )
即使您的对象不是不可变的,如果您只使用基于身份的相等/哈希实现,即不受对象内部状态以任何方式影响的实现,您也可能会摆脱该实现。
关于 cocoa 的 NSDictionary : why are keys copied?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2394083/