If I have a data tree that is something like :
NSMutableDictionary (dict1)
NSMutableDictionary (dict2)
NSMutableArray (array)
NSMutableDictionary (dict3)
Key1
Key2
NSMutableDictionary (dict_n)
Keyn
Keyn
NSMutableDictionary (dict_n)
NSMutableArray (array_n)
NSMutableDictionary (dict_n)
Keyn
Keyn
NSMutableDictionary (dict_n)
Keyn
Keyn
If I want to change the value of Key1, is there a simplier way than...
getting dict1
then getting dict2
then getting array
then getting dict3
converting dict3 to a mutable Dictionary
then setting key1
Converting array to a mutable array
then setting dict3 into array
converting dict2 to a mutable Dictionary
then setting array into dict2
converting dict1 to a mutable Dictionary
then setting dict2 into dict1
Doing that for each value I have to change is a real headache, and really code consuming.
You can't send a message to an object unless you have a pointer to that object, so in a basic sense the answer to your question is no, there's no other way.
However, one presumes that this data structure that you have represents some sort of data model. As such, it should probably be contained in some sort of model class that understands its parts, and that class should be the only one that needs to understand how the data is stored. The model class should offer a higher-level interface to the data. Say dict3 represents one particular vehicle in a fleet, and the keys are things like "vehicleTag", "registrationDate", "purchaseDate", etc. Maybe the dictionaries at the dict2 level the fleets in different regions, and dict2 itself represents the northeast fleet. Then the VehiclePool class, your model class which stores all the data, might offer methods like:
-registrationDateForVehicle:(int)vehicleIndex inFleet:(NSString*)fleetKey;
-setRegistrationDate:(NSDate*)regDate forVehicle:(int)vehicleIndex inFleet:(NSString*)fleetKey;
I'm not sure I'd really want an API like that -- I'd prefer to get the list of vehicles for a given fleet and then operate on those with simpler accessors, but you seem to want to avoid several levels of accessors. The point here is that you shouldn't be writing a ton of code to do the operations you need; you should write methods that know how to access the data and then call those.
The NSDictionary
documentation states:
In general, a key can be any object (provided that it conforms to the NSCopying protocol—see below), but note that when using key-value coding the key must be a string (see “Key-Value Coding Fundamentals”).
Therefore, if your keys (and sub-keys) are all strings, you can do the following to retrieve and set values:
id myNestedObject = [topLevel valueForKeyPath:@"firstKey.secondKey.thirdKey"];
[topLevel setObject:newNestedObject forKeyPath:@"firstKey.secondKey.thirdKey"];