使用非可复制对象作为NSMutableDictionary的键?

Eon*_*nil 1 key objective-c nsmutabledictionary

我试图找出这个代码引用:Cocoa:带枚举键的字典?

+ (NSValue*)valueWithReference:(id)target
{
    return [NSValue valueWithBytes:&target objCType:@encode(id*)];
}
Run Code Online (Sandbox Code Playgroud)

和,

[table setObject:anObject forKey:[NSValue valueWithReference:keyObject]];
Run Code Online (Sandbox Code Playgroud)

但感觉不好.有什么建议?

Chu*_*uck 9

你说得对,这不好.

首先,你编码错误的类型(它应该是,但@encode(id)不是@encode(id*)),但在大多数情况下,这不应该导致一个大问题.

更大的问题是这完全忽略了内存管理.该对象不会被保留或复制.如果其他一些代码释放它,它可能会消失,然后你的字典键将是一个盒装指针,指向垃圾甚至完全不同的对象.这基本上是世界上最先进的悬空指针.

你有两个不错的选择:

  1. 您可以将NSCopying添加到类中,也可以创建可复制的子类.

    • 此选项仅适用于可以有意义地复制的对象.这是大多数类,但不一定全部(例如,有多个对象表示相同的输入流可能不好)
    • 即使对于有意义的课程来说,实现复制也会很痛苦 - 本身并不困难,但有点烦人
  2. 您可以使用CFDictionary API创建字典.由于Core Foundation类型没有通用的复制功能,因此CFDictionary默认只保留其键(尽管您可以根据需要自定义其行为).但CFDictionary也与NSDictionary无关联,这意味着您可以将其CFDictionaryRef转换为NSDictionary*(或NSMutableDictionary*),然后将其视为任何其他NSDictionary.

    • 这意味着你用作键的对象hash在字典中不能改变(至少不会影响它的值) - 确保不会发生这种情况是为什么NSDictionary通常想要复制它的键