-2

I'm trying to insert an object in my dictionary, but first, I want to test if it's a NSMutableDictionary :

if ([[[self.response objectForKey:@"X"] objectAtIndex:0] isKindOfClass:[NSMutableDictionary class]]) {
        [[[self.response objectForKey:@"X"] objectAtIndex:0]setObject:@"Hello" forKey:@"Y"];
    } 

I get this issue :

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
amorfis
  • 15,390
  • 15
  • 77
  • 125
Nabil El
  • 972
  • 1
  • 10
  • 24
  • 3
    Look at the doc of `isKindOfClass`, there is a beautiful example with the "NOT TO DO THIS" which matches your issue. – Larme Mar 14 '14 at 10:29
  • Try this: `id dictionary = [[self.response objectForKey:@"X"] objectAtIndex:0]; if ([dictionary isKindOfClass:[NSMutableDictionary class]]) { [dictionary setObject:@"Hello" forKey:@"Y"];`. This more readable. } – bsarr007 Mar 14 '14 at 10:35
  • @Nabil El Is `self.response` mutable? – Akhilrajtr Mar 14 '14 at 10:37
  • @bsarr007 readability is not his issue. – Rukshan Mar 14 '14 at 10:37
  • @whitewolf09 sure, but this would help readers! And improve his question. – bsarr007 Mar 14 '14 at 10:38
  • @bsarr007 that's why there's an EDIT button in the question section itself. :) – Rukshan Mar 14 '14 at 10:39
  • @Akhilrajtr Yes it's mutable – Nabil El Mar 14 '14 at 10:40
  • @whitewolf09 I agree with you but i can't really change his code before he test it programmatically inside his program, this is not typo! – bsarr007 Mar 14 '14 at 10:41
  • check `NSLog(@"%@",[[[self.response objectForKey:@"X"] objectAtIndex:0] class]);` what it prints. – Anoop Vaidya Mar 14 '14 at 10:43
  • Well this is wrong to do so.... You should make a `mutableCopy` of this then you can update it. It is getting crash because of immutable object. `NSMutableDictionary *dict = [[[self.response objectForKey:@"X"] objectAtIndex:0] mutableCopy]; [dict setObject:@"Hello" forKey:@"Y"];` – TheTiger Mar 14 '14 at 10:49

3 Answers3

3

You can check for the same selector which is crashing,

if([object respondsToSelector:@selector(setObject:forKey:)]) {
    //If YES, it is NSMutableDictionary
}
else { 
    //Not mutable
}

Hope that helps!

Amar
  • 13,202
  • 7
  • 53
  • 71
2

Use isMemberOfClass instead of isKindOfClass

Rukshan
  • 7,902
  • 6
  • 43
  • 61
  • Why this should work and no the isKindOfClass, can you be more explicit? – bsarr007 Mar 14 '14 at 10:36
  • 1
    Because NSDictionary is a cluster class. ie Although you call it an NSDictionary / NSMutableDictionary, what you are actually given by the initializer (or instance type) is an undocumented subclass.. do some reading on class clusters. NSArray is another – Jef Mar 14 '14 at 12:09
1

Try this,

if ([[[self.response objectForKey:@"X"] objectAtIndex:0] isKindOfClass:[NSDictionary class]]) {

    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[[self.response objectForKey:@"X"] objectAtIndex:0]];
    [dict setObject:@"Hello" forKey:@"Y"];
    NSMutableArray *xArray = [NSMutableArray arrayWithArray:[self.response objectForKey:@"X"]];
    [xArray replaceObjectAtIndex:0 withObject:dict];
    [self.response setObject:xArray forKey:@"X"];
} 
Akhilrajtr
  • 5,170
  • 3
  • 19
  • 30