Date
1 - 4 of 4
Replace object at key path in NS[Mutable]Dictionary
Jonathan Taylor
HiI all,
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? Cheers Jonny. [University of Glasgow: The Times Scottish University of the Year 2018] |
|
Have you tried using NSPropertyListSerialization with the NSPropertyListMutableContainers option? That should make all the nested dictionaries/arrays mutable. —Jens |
|
Jon Gotow
On Jan 2, 2018, at 10:55 AM, Jonathan Taylor <jonathan.taylor@...> wrote: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 |
|
Jonathan Taylor
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. Thankyou Jens (and also Jon) for your reply. That was just what I was hoping for - an API that I didn’t even know where to look for (though obvious in retrospect!). That should do very nicely. |
|