使用NSMutableDictionary的对象键(Objective-C)

时间:2011-05-24 06:43:47

标签: objective-c nsdictionary key-value

我想存储一堆键值对,键是我自己的对象(ObjectA),它继承自NSObject,值为int。
我正在尝试使用NSMutableDictionary。我知道你只能在字典中存储对象类型,所以我有以下内容:

id value = [NSNumber numberWithInt:my_number];

[[self dictionary] setObject:value forKey:myObjectA];

现在这给了我一个错误,说

  

- [ObjectA copyWithZone:]:无法识别的选择器发送到实例

这很好,我知道对象密钥需要实现NSCopying协议。然而,我读到你可以通过使用NSValue包装对象来实现这一点。

有人可以解释我如何包装我的对象,以及如何通过密钥找到值?我仍然可以使用dictionary objectForKey:myObjectA或者我在搜索时还必须使用NSValue对象包装myObjectA吗?或者我应该在我的自定义类上实现NSCopying,还是使用字符串键?

我正在寻找这种使用字典的最简单和最简单的方法,如果我必须实现一个字符串键并使用setValue:forKey:相反,但如果可以,我宁愿使用对象键。

4 个答案:

答案 0 :(得分:10)

始终复制字典键。因此,您只需要为您的班级实施NSCopying协议,这只是copyWithZone:方法。

此外,您应该为您的班级实施isEqual:方法。

编辑:如何实施copyWithZone:取决于多种因素(主要因素:深拷贝与浅拷贝)。请参阅Apple的Implementing Object Copy指南和this SO answer

答案 1 :(得分:6)

您可以使用以下内容将id转换为NSValue:

NSValue* value = [NSValue valueWithNonretainedObject:object];
...
id object_ = [value nonretainedObjectValue];

但您需要管理字典之外的所有权。这将是一团糟。采用NSCopying更好。


还有第四个选项:使用CFDictionary,它允许对象只能是CFRetain / CFReleased,而不是复制。

CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
     kCFAllocatorDefault, 0,
     &kCFTypeDictionaryKeyCallBacks,
     &kCFTypeDictionaryValueCallBacks
);

...

CFDictionarySetValue(dict, myObjectA, value);
...

CFRelease(dict);

如果您正在为Mac或iOS 6及更高版本编程,请尝试使用NSMapTable。

NSMapTable* dict = [[NSMapTable mapTableWithStrongToStrongObjects] retain];
...
[dict setObject:@"?" forKey:foo];
...
[dict release];

答案 2 :(得分:2)

在iOS 6中,您可以使用NSMapTable(https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/NSMapTable_class/Reference/NSMapTable.html),它允许您为键和对象选择弱/强属性。

答案 3 :(得分:0)

您无需使用NSValue包装对象。你有什么工作,除了你错过了一块。对于myObjectA的类,您需要采用NSCopying协议(请参阅the docs了解要添加的内容)。一旦添加了上面发布的代码,就可以正常工作。

您可能希望考虑在您自己的对象上使用字符串作为密钥。如果将使用键值编码来访问密钥,则密钥必须是字符串。因此,如果您可以在任何使用字典的地方利用键值编码,那么使用字符串将使生活更轻松。