NSInvalidArgumentException/copyWithZone 异常与 NSMutableDictionary
Posted
技术标签:
【中文标题】NSInvalidArgumentException/copyWithZone 异常与 NSMutableDictionary【英文标题】:NSInvalidArgumentException/copyWithZone exception with NSMutableDictionary 【发布时间】:2009-06-25 17:45:21 【问题描述】:我有一个用于封装 ABRecordID 的类,当它用作添加到 NSMutableDictionary 的键时,我得到了运行时异常:
"NSInvalidArgumentException: *** -[MyRecordId copyWithZone:]:无法识别的选择器发送到 实例”
MyRecordId 声明为:
@interface MyRecordId : NSObject
ABRecordID abRecordId;
-(id)initWithId:(ABRecordID)anABRecordId;
@property (nonatomic) ABRecordID abRecordId;
@end
添加到字典:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
MyRecordId *recordId = [[MyRecordId alloc] initWithId:anABRecordId];
[dict setObject:@"hello" forKey:recordId];
最后一行导致了异常。我知道您不能将非对象类型存储为字典的键,但我认为将其包装在 NSObject 派生类中就可以了。
我不应该将 ABRecordID 存储在其他对象中吗?我应该做点别的吗?
【问题讨论】:
【参考方案1】:使用 NSNumber 将 ABRecordID 存储在 Obj-C 类中:
[dict setObject:@"hello" forKey:[NSNumber numberWithInt:recordId]];
要再次获取recordId,请执行以下操作:
recordId = [[dict objectForKey:@"hello"] intValue];
【讨论】:
【参考方案2】:NSDictionary 键需要实现 NSCopying 协议。这就是为什么它告诉你你的对象没有响应copyWithZone:
。
【讨论】:
【参考方案3】:您用作键值的对象的类应符合NSCopying
协议。
基本上它应该实现copyWithZone:
方法。
您应该使用NSValue
类,而不是使用您自己的类来包装您的非对象变量,该类专为此目的而设计并支持NSCopying
协议。
【讨论】:
我不知道 NSValue 最适合这个目的。我将使用哪个初始化程序来使用“ABRecordID”构造它? 我个人将使用“NSValue valueWithNonretainedObject”,应该适合你。请记住,它当然不会为您保留您的对象...【参考方案4】:对于像我这样面临挑战的编码,请确保 setObject 的参数是正确的。我只是在这个错误上浪费了几个小时,然后才注意到我把它们颠倒了!
【讨论】:
亲爱的,这也是我的问题,谢谢【参考方案5】:您也可以将 NSNumber 用于此目的,因为它继承自 NSValue。
【讨论】:
【参考方案6】:Diederik 走在正确的道路上,但鉴于 ABRecordID
的类型,我建议使用 NSNumber
(NSValue
子类)。您可以将-initWithInt:
用于ABRecordID
,这是一个int32_t
。
【讨论】:
以上是关于NSInvalidArgumentException/copyWithZone 异常与 NSMutableDictionary的主要内容,如果未能解决你的问题,请参考以下文章