Objective c 使用不可复制对象作为NSMutableDictionary的键?
我试图找出以下代码: 以及Objective c 使用不可复制对象作为NSMutableDictionary的键?,objective-c,key,nsmutabledictionary,Objective C,Key,Nsmutabledictionary,我试图找出以下代码: 以及 但感觉有些不好。有什么建议吗?你完全正确,这不好 首先,您编码的类型是错误的(它应该是@encode(id),而不是@encode(id*)),但在大多数情况下,这不会造成大问题 更大的问题是,这完全忽略了内存管理。对象将不会被保留或复制。如果其他代码释放了它,它可能会消失,然后您的字典键将是一个指向垃圾的盒装指针,甚至是一个完全不同的对象。这基本上是世界上最先进的 您有两个很好的选择: 您可以将NSCopying添加到类中,也可以创建一个可复制的子类 此选项仅适用
但感觉有些不好。有什么建议吗?你完全正确,这不好 首先,您编码的类型是错误的(它应该是
@encode(id)
,而不是@encode(id*)
),但在大多数情况下,这不会造成大问题
更大的问题是,这完全忽略了内存管理。对象将不会被保留或复制。如果其他代码释放了它,它可能会消失,然后您的字典键将是一个指向垃圾的盒装指针,甚至是一个完全不同的对象。这基本上是世界上最先进的
您有两个很好的选择:
- 此选项仅适用于可以有意义地复制的对象。这是大多数类,但不一定是所有类(例如,多个对象代表同一个输入流可能不好)
- 实现复制即使对于有意义的类来说也是一件痛苦的事情——从本质上来说并不困难,但有点烦人
CFDictionaryRef
转换为NSDictionary*
(或NSMutableDictionary*
)然后将其与任何其他NSDictionary一样处理
- 这意味着您用作键的对象在字典中时不得更改(至少不能以影响其
哈希值的方式更改)-确保不会发生这种情况是NSDictionary通常希望复制其键的原因
你完全正确,这不好 首先,您编码的类型是错误的(它应该是
@encode(id)
,而不是@encode(id*)
),但在大多数情况下,这不会造成大问题
更大的问题是,这完全忽略了内存管理。对象将不会被保留或复制。如果其他代码释放了它,它可能会消失,然后您的字典键将是一个指向垃圾的盒装指针,甚至是一个完全不同的对象。这基本上是世界上最先进的
您有两个很好的选择:
- 此选项仅适用于可以有意义地复制的对象。这是大多数类,但不一定是所有类(例如,多个对象代表同一个输入流可能不好)
- 实现复制即使对于有意义的类来说也是一件痛苦的事情——从本质上来说并不困难,但有点烦人
CFDictionaryRef
转换为NSDictionary*
(或NSMutableDictionary*
)然后将其与任何其他NSDictionary一样处理
- 这意味着您用作键的对象在字典中时不得更改(至少不能以影响其
哈希值的方式更改)-确保不会发生这种情况是NSDictionary通常希望复制其键的原因
我不能百分之百确定这个解决方案的正确性,但我发布它只是以防万一 如果您不想使用CFDictionary,也许可以使用以下简单类别:
@implementation NSMutableDictionary(NonCopyableKeys)
- (void)setObject:(id)anObject forNonCopyableKey:(id)aKey {
[self setObject:anObject forKey:[NSValue valueWithPointer:aKey]];
}
- (id)objectForNonCopyableKey:(id)aKey {
return [self objectForKey:[NSValue valueWithPointer:aKey]];
}
- (void)removeObjectForNonCopyableKey:(id)aKey {
[self removeObjectForKey:[NSValue valueWithPointer:aKey]];
}
@end
这是我在网上看到的一个类似方法(找不到原始源代码)的推广,该方法使用NSMutableDictionary来存储带有UITouch键的对象
与Chuck的答案中相同的限制也适用:用作键的对象的更改不得影响其哈希值,并且在字典中时不得释放该对象
还要确保不要将-(void)setObject:(id)一个对象与noncopyableKey:(id)aKey
和-(id)objectForKey:(id)aKey
方法混在一起,因为它不起作用(后者将返回nil
)
这似乎很好,但可能有一些我没有想到的不必要的副作用。如果有人发现此解决方案有任何其他问题或警告,请发表评论。我不能100%确定此解决方案的正确性,但我将发布此解决方案以防万一 如果您不想使用CFDictionary,也许可以使用以下简单类别:
@implementation NSMutableDictionary(NonCopyableKeys)
- (void)setObject:(id)anObject forNonCopyableKey:(id)aKey {
[self setObject:anObject forKey:[NSValue valueWithPointer:aKey]];
}
- (id)objectForNonCopyableKey:(id)aKey {
return [self objectForKey:[NSValue valueWithPointer:aKey]];
}
- (void)removeObjectForNonCopyableKey:(id)aKey {
[self removeObjectForKey:[NSValue valueWithPointer:aKey]];
}
@end
这是我在网上看到的一个类似方法(找不到原始源代码)的推广,该方法使用NSMutableDictionary来存储带有UITouch键的对象
与Chuck的答案中相同的限制也适用:用作键的对象的更改不得影响其哈希值,并且在字典中时不得释放该对象
还要确保不要将-(void)setObject:(id)一个对象与noncopyableKey:(id)aKey
和-(id)objectForKey:(id)aKey
方法混在一起,因为它不起作用(后者将返回nil
)
这似乎很好,但可能有一些我没有想到的不必要的副作用。如果任何人发现此解决方案有任何其他问题或警告,请发表评论。供以后参考 现在我知道还有更多的选择
NSCopying
协议中的方法,并返回self
,而不是复制自身。(如果不使用ARC,则应保留该值)此外,还应确保对象始终为-hash
返回相同的值
@implementation NSMutableDictionary(NonCopyableKeys)
- (void)setObject:(id)anObject forNonCopyableKey:(id)aKey {
[self setObject:anObject forKey:[NSValue valueWithPointer:aKey]];
}
- (id)objectForNonCopyableKey:(id)aKey {
return [self objectForKey:[NSValue valueWithPointer:aKey]];
}
- (void)removeObjectForNonCopyableKey:(id)aKey {
[self removeObjectForKey:[NSValue valueWithPointer:aKey]];
}
@end