Cocoa 的 NSDictionary:为什么要复制键?
所有在 NS(Mutable)Dictionaries 中用作键的对象都必须支持 NSCopying 协议,并且这些对象在字典中使用时会被复制。
我经常想使用较重的对象作为键,只是将一个对象映射到另一个对象。当我这样做时,我真正的意思是有效的:(
[dictionary setObject:someObject forKey:[NSValue valueWithPointer:keyObject]];
“当我回来并再次给你这个相同的关键对象实例时,给我相同的值。”)
......这正是我最终要做的绕过有时这种设计。 (是的,我知道桌面 Cocoa 中的 NSMapTable;但是 iPhone 不支持这一点。)
但是我真正不明白的是为什么复制密钥首先是必要的或可取的。它为实现或调用者买了什么?
All objects used as keys in NS(Mutable)Dictionaries must support the NSCopying protocol, and those objects are copied when they're used in the dictionary.
I frequently want to use heavier weight objects as keys, simply to map one object to another. What I really mean when I do that is effectively:
[dictionary setObject:someObject forKey:[NSValue valueWithPointer:keyObject]];
("When I come back and hand you this same key object instance again, get me that same value out.")
...which is exactly what I end up doing to get around this design sometimes. (Yes, I know about NSMapTable in desktop Cocoa; but e.g. iPhone doesn't support this.)
But what I don't really get is why copying the key is necessary or desirable in the first place. What does it buy the implementation or caller?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
该副本确保用作键的值在用作键时不会“暗中”更改。考虑可变字符串的示例:
假设字典没有复制键,而只是
保留
它。如果现在,在稍后的某个时刻,原始字符串被修改,那么即使您使用完全相同的键对象(即一个),您也很可能不会再次在字典中找到存储的值key
指向上面示例中的位置)。为了保护自己免受此类错误的影响,字典会复制所有键。
顺便说一下,请注意,将
-copyWithZone:
定义为仅执行return [self keep]
非常简单。如果你的对象是不可变的,那么这是允许的,并且是好的代码,并且 NSCopying 合约是专门设计的,使得返回的对象必须是(有点,有点)不可变的:(来自 NSCopying 参考)
和
(来自 -copyWithZone:参考)
即使您的对象不是不可变的,如果您只使用基于身份的相等/哈希实现,即不受对象内部状态以任何方式影响的实现,您可能会摆脱该实现。
The copy ensures that the values used as keys don't change "underhand" while being used as keys. Consider the example of a mutable string:
Let's assume that the dictionary did not copy the key, but instead just
retain
ed it. If now, at some later point, the original string is modified, then it is very likely that you are not going to find your stored value in the dictionary again even if you use the very same key object (i.e., the onekey
points to in the example above).In order to protect yourself against such a mistake, the dictionary copies all keys.
Note, by the way, that it is simple enough to define
-copyWithZone:
as just doingreturn [self retain]
. This is allowed and good code if your object is immutable, and theNSCopying
contract is specifically designed such that the object returned has to be (sorta, kinda) immutable:(from NSCopying Reference)
and
(from -copyWithZone: Reference)
Even if your objects are not immutable, you might get away with that implementation if you only ever use identity-based equality/hash implementations, i.e., implementations which are not affected in any way by the object's internal state.
如果您想将指针存储为键,那么您需要使用
+valueWithPointer:
将它们包装在NSValue
对象中。If you want to store pointers as keys then you'll need to wrap them in a
NSValue
object with+valueWithPointer:
.从 iOS 6 开始,如果你想使用指针作为键,你可以使用
NSMapTable
对象,请参阅 http:// nshipster.com/nshashtable-and-nsmaptable/您可以指定键和/或值是强保留还是弱保留:
有时可能合适的另一个选项是使用
NSCache
,它牢固地保存键并且实际上是线程安全的。Since iOS 6 if you want to use pointers as keys, you can use the
NSMapTable
object, see http://nshipster.com/nshashtable-and-nsmaptable/You can specify whether keys and/or values are stongly or weakly held:
Another option that could be appropriate sometimes is to use
NSCache
, which holds keys strongly and is actually thread-safe.