简体   繁体   中英

Objective-C: Static NSDictionary throws NSInvalidArgumentException when I add to it

I have a method that is supposed to take an NSManagedObject, copy its attributes into a dictionary, then add the dictionary to an NSMutableArray in a static NSMutableDictionary with NSManagedObjectID keys. The problem is that it crashes when I try to add to a static NSMutableDictionary and only works if I make one on the spot.

The problem is definitely related to the static NSMutableDictionary changes because I do not get the exception if I use a non-static dictionary. It's defined like this (above @implementation):

static NSMutableDictionary* changes = nil;

And here is the method:

+ (void)acceptChange: (NSManagedObject *)change{
if (!changes){
    NSLog(@"Making new changes dicitonary"); //it prints this when I run
    changes = [[NSDictionary alloc] init];
}
NSManagedObjectID* objectID = change.objectID;
NSMutableArray* changeArray = [changes objectForKey: objectID];
bool arrayDidNotExist = NO;
if (!changeArray){
    changeArray = [[NSMutableArray alloc] init];
    arrayDidNotExist = YES;
}
[changeArray addObject: [(this class's name) copyEventDictionary: change]]; //copies the NSManagedObject's attributes to an NSDictionary, assumedly works
if (arrayDidNotExist) [changes setObject: changeArray forKey: objectID];//throws the  exception

//If I do the exact same line as above but do it to an [[NSMutableDictionary alloc] init] instead of the static dictionary changes, it does not throw an exception.

if (arrayDidNotExist) NSLog(@"New array created");
NSLog(@"changeArray count: %d", changeArray.count);
NSLog(@"changes dictionary count: %d", changes.count);

}

The exact exception message is this:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0xa788e30'

Use NSMutableDictionary instead of NSDictionary . You are getting exception as because , NSMutableDictionary can be modified dynamically, NSDictionary cannot. .

NSMutableDictionary is subclass of NSDictionary . So all methods of NSDictionary is accessible via NSMutableDictionary object. Moreover NSMutableDictionary also adds complementary methods to modify things dynamically, such as the method setObject:forKey:

EDIT

You have initialized it using NSDictionary instead of `NSMutableDictionary.

if (!changes){
    NSLog(@"Making new changes dicitonary"); //it prints this when I run
    //changes = [[NSDictionary alloc] init]; 
                ^^^^^^^^^^^^^^ ------------------> Change this. 
    changes = [[NSMutableDictionary alloc] init];
}

[__NSDictionaryI setObject:forKey:] shows that your dictionary is immutable. You are actually initializing your dictionary as immutable. That's why its raising exception on adding an object.

Here change this line:

if (!changes){
   ....
    changes = [[NSDictionary alloc] init];
}

to:

if (!changes){
    ....
    changes = [[NSMutableDictionary alloc] init];
}

You declared your dictionary to be of NSMutableDictionary, so at compile time your dictionary is of NSMutable dictionary, but at run time it is NSDictionary as you allocated it as NSDictionary, to which you can not make changes, hence the exception. Please define the dictionary as :-

changes = [[NSMutableDictionary alloc] init];

If you read the description of your exception, it says the same thing.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM