Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding keys to Nested NSDictionary

I am having problems creating new keys for a Nested NSDictionary. Here's what I have done

I have this kind of NSMutableDictionary

  NSMutableDictionary *Ga=[NSMutableDictionary dictionaryWithDictionary:@{@"Node1" :@{@"SubNode11" :@40,@"SubNode12":@30}}];

Which NSLogs as:

Node1 =     {
    SubNode11 = 40;
    SubNode12 = 30;
};

Now to add another root key and a nested key I did this,

[Ga setObject:@{@"SubNode21" : @555} forKey:@"Node2"];

Now the NSLog outputs:

Node1 =     {
    SubNode11 = 40;
    SubNode12 = 30;
};
Node2 =     {
    SubNode21 = 555;
};
}

I need to add another key to an existing Node, say SubNode22=345; for Node2 in a separate line of code, so I thought this might work

[[Ga objectForKey:@"Node2"] setObject:@5555 forKey:@"SubNode22"];

But this show Error "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance"

I don't what the Problem is,, this method seems straight forward to me.. Any solution please.

like image 965
yabtzey Avatar asked Aug 09 '13 17:08

yabtzey


2 Answers

The problem here has nothing to do with nesting. It has to do with mutable verse immutable. If the dictionary isn't mutable you can't add to it.

The error message is telling you, that NSDictionary's don't have a method called setObject:ForKey: because that is a method of NSMutableDictionary. Using Apples new literal dictionaries @{ key: object} only creates immutable dictionaries.

So what you actually need is to make sure you're created NSMutableDictionarys using either [NSMutableDictionary dictionaryWithObjectsAndKeys:]; or [@{ Key: Object } mutableCopy]

So here is your code changed

NSMutableDictionary *subNode = [NSMutableDictionary dictionaryWithObjectsAndKeys:@40, @"SubNode11", @30, @"SubNode12", nil];
NSMutableDictionary *Ga = [NSMutableDictionary dictionaryWithObjectsAndKeys:subNode, @"Node 1", nil];
[Ga setObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@555, @"SubNode21", nil] forKey:@"Node2"];
[[Ga objectForKey:@"Node2"] setObject:@5555 forKey:@"SubNode22"];

You can still use some of the new subscripting features though. For instance you can change the code to something like this thats more readable doing the same things:

NSMutableDictionary *Ga = [NSMutableDictionary dictionary];

// Create SubNodes
NSMutableDictionary *subNode1 = [NSMutableDictionary dictionary];
subNode1[@"SubNode11"] = @40;
subNode1[@"SubNode12"] = @30;

NSMutableDictionary *subNode2 = [NSMutableDictionary dictionary];
subNode2[@"SubNode21"] = @555;

// Set SubNodes to Main Node Container
Ga[@"Node1"] = subNode1;
Ga[@"Node2"] = subNode2;

// Set a nested subnode's value.
Ga[@"Node2"][@"SubNode22"] = @5555;
like image 154
Ryan Poolos Avatar answered Nov 20 '22 20:11

Ryan Poolos


The problem is that your outer dictionary is an NSMutableDictionary, but your inner ones (the ones created with just the @{} syntax) are immutable NSDictionaries. You'll need to explicitly make them all mutable.

like image 2
Chuck Avatar answered Nov 20 '22 20:11

Chuck