On Jan 2, 2018, at 10:55 AM, Jonathan Taylor <jonathan.taylor@...> wrote:
I have a dictionary that has been loaded from a plist file, which has a deep structure of dictionaries within dictionaries. I would like to modify just one key-value pair deep in that hierarchy. Is there a neat off-the-shelf way of doing that?
I can load the plist file as an NSMutableDictionary, but it seems that only makes the top level dictionary mutable. The dictionaries-within-dictionaries are still immutable. Suppose I want to modify the value associated with the key path dict.next_level.deeper.even_deeper.key. The only way I can see to achieve this is to replicate “even_deeper" as a mutable dictionary, modify the value of “key” in it, replicate “deeper” and modify “even_deeper”, replicate “next_level” and modify “deeper”, and finally modify “next_level” within “dict”.
I could write recursive code to do that, but it feels as if there ought to be a more straightforward way of achieving what I want. Can anyone point me at something I have missed?
I've always just converted the entire dictionary and its contents to mutable objects. I've included some code below for the necessary categories to implement "mutableCopyDeep" methods. It does a deep traversal to create mutable copies of everything in an NSDictionary or NSArray.
- Jon
#import "MutableCopyDeep.h"
@implementation NSDictionary (MutableCopyDeep)
- (NSMutableDictionary*)mutableCopyDeep
{
NSMutableDictionary* copy = [[NSMutableDictionary alloc] init];
[self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
id cobj = [obj mutableCopyDeep];
[copy setObject:cobj forKey:key];
#if !__has_feature(objc_arc)
[cobj release];
#endif
}];
return copy;
}
@end
#pragma mark -
@implementation NSArray (MutableCopyDeep)
- (NSMutableArray*)mutableCopyDeep
{
NSMutableArray* copy = [[NSMutableArray alloc] init];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id cobj = [obj mutableCopyDeep];
[copy addObject:cobj];
#if !__has_feature(objc_arc)
[cobj release];
#endif
}];
return copy;
}
@end
#pragma mark -
@implementation NSObject (MutableCopyDeep)
- (id)mutableCopyDeep
{
if([self respondsToSelector:@selector(mutableCopyWithZone:)])
return [self mutableCopy];
else
return [self copy];
}
@end