Reputation: 303
I had a problem in my project where I declared in the header file an NSMutableDictionary property like so:
@property (copy, nonatomic) NSMutableDictionary *DataDict ;
Now in the implementation file, I go ahead and initialise this dictionary because I am gonna use it, like so:
DataDict = [[NSMutableDictionary alloc]init];
Now when I did this, the minute I try to add something to this dictionary I would get this error message:
-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0x885ae60 2012-10-19 16:51:56.040 testing[2297:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0x885ae60'
After a while and running through my project a thousand times, I decided to uncomment my initialization line, like so
//DataDict = [[NSMutableDictionary alloc]init];
and that fixed the problem.
My question is: Why?
Upvotes: 8
Views: 4869
Reputation: 177
I have this exact problem. No combination of retain/copy/strong/weak, etc do the trick. What does work is to create a temporary Mutable Dictionary, load it up and then set my original equal to it.
NSMutableDictionary * tempD = [[NSMutableDictionary alloc] init];
[tempD setObject: epsTapeCut forKey:LWPrintParameterKeyTapeCut];
[tempD setObject: epsCopies forKey:LWPrintParameterKeyCopies];
[tempD setObject: epsHalfCut forKey:LWPrintParameterKeyHalfCut];
[tempD setObject: epsPrintSpeed forKey:LWPrintParameterKeyPrintSpeed];
[tempD setObject: epsDensity forKey:LWPrintParameterKeyTapeWidth];
self.ePSprintSettings = tempD;
This fails:
[self.ePSprintSettings setObject: epsTapeCut forKey:LWPrintParameterKeyTapeCut];
Declaration:
@property (nonatomic, retain) NSMutableDictionary *ePSprintSettings;
(But again, no combination of attributes makes a difference.)
Initialization:
self.ePSprintSettings = (NSMutableDictionary *)[myUserDefaults dictionaryForKey:kEpsPrintSettings];
Thank you for helping me understand.
I'm happy enough that this works, but I'd like to understand why.
Upvotes: 0
Reputation: 35706
The problem is in the way you have defined your property. If you change it to:
@property (strong, nonatomic) NSMutableDictionary *DataDict ;
instead of copy
everything should be fine.
This happens because you basically say that you want a copy of your object through your generated accessors, which returns an NSDictionary
instead (an immutable copy).
You can find more on objective-c properties here.
Just as a sidenote: objective-c ivars usually start with a lowercase letter (uppercase names are used for classes), so dataDict
should be preferred over DataDict
.
Upvotes: 15
Reputation: 7874
It is because the property have "copy" attribute so NSMutableDictionary instance alloc/init-ed is "copy"'ed using "copy" method, and "copy" method create not NSMutableDictionary but NSDictionary. ("mutableCopy" will create NSMutableDictionary).
Probably, you can use "retain" instead of "copy" as attributes.
@property (retain, nonatomic) NSMutableDictionary *DataDict ;
Or, just without "copy"/"retain" but use ARC.(Automatic reference counting).
Upvotes: 2