Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSInvalidArgumentException/copyWithZone exception with NSMutableDictionary

Tags:

iphone

I have a class that I'm encapsulating ABRecordID with and when it's used as a key to add to an NSMutableDictionary, I get the run-time exception:

"NSInvalidArgumentException: *** -[MyRecordId copyWithZone:]: unrecognized selector sent to instance"

MyRecordId declared as:

@interface MyRecordId : NSObject {
    ABRecordID abRecordId;
}

-(id)initWithId:(ABRecordID)anABRecordId;
@property (nonatomic) ABRecordID abRecordId;

@end

Adding to dictionary:

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
MyRecordId *recordId = [[MyRecordId alloc] initWithId:anABRecordId];
[dict setObject:@"hello" forKey:recordId];

The last line causes the exception.. I know that you can't store non-object types as keys for a dictionary but I thought that wrapping it up in NSObject derived class would make it okay.

Am I not supposed to store ABRecordID in other objects? Should I be doing something else?

like image 911
Robin Jamieson Avatar asked Jun 25 '09 17:06

Robin Jamieson


4 Answers

Use NSNumber to store the ABRecordID in an Obj-C class:

[dict setObject:@"hello" forKey:[NSNumber numberWithInt:recordId]];

to obtain the recordId again, do:

recordId = [[dict objectForKey:@"hello"] intValue];
like image 87
Marco Mustapic Avatar answered Nov 20 '22 12:11

Marco Mustapic


NSDictionary keys need to implement the NSCopying protocol. That's why it's telling you your object doesn't respond to copyWithZone:.

like image 41
Chuck Avatar answered Nov 20 '22 12:11

Chuck


The class of the object you use as a key value should conform to the NSCopying protocol. Basically it should implement the copyWithZone: method.

Instead of using your own class to wrap your non-object variable in, you should use NSValue class, which is designed for this purpose and supports the NSCopying protocol.

like image 6
diederikh Avatar answered Nov 20 '22 10:11

diederikh


For the coding challenged like me, make sure the arguments to setObject are the right way around. I just wasted hours on this error before I noticed I had them reversed!

like image 1
Symmetric Avatar answered Nov 20 '22 11:11

Symmetric