我想存储一堆键值对,键是我自己的对象(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:相反,但如果可以,我宁愿使用对象键。
答案 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了解要添加的内容)。一旦添加了上面发布的代码,就可以正常工作。
您可能希望考虑在您自己的对象上使用字符串作为密钥。如果将使用键值编码来访问密钥,则密钥必须是字符串。因此,如果您可以在任何使用字典的地方利用键值编码,那么使用字符串将使生活更轻松。