How to loop through a nested hierarchy of NSDictionaries and NSArrays and convert all to mutable copies?

ios, nsarray, nsdictionary, objective-c, recursion

Solution

The following method creates a nested (deep) mutable copy of nested arrays, dictionaries and sets. It can also be used to create mutable copies of non-collection objects inside the hierarchy, such as strings.

@interface NSObject (MyDeepCopy)
-(id)deepMutableCopy;
@end

@implementation  NSObject (MyDeepCopy)
-(id)deepMutableCopy
{
    if ([self isKindOfClass:[NSArray class]]) {
        NSArray *oldArray = (NSArray *)self;
        NSMutableArray *newArray = [NSMutableArray array];
        for (id obj in oldArray) {
            [newArray addObject:[obj deepMutableCopy]];
        }
        return newArray;
    } else if ([self isKindOfClass:[NSDictionary class]]) {
        NSDictionary *oldDict = (NSDictionary *)self;
        NSMutableDictionary *newDict = [NSMutableDictionary dictionary];
        for (id obj in oldDict) {
            [newDict setObject:[oldDict[obj] deepMutableCopy] forKey:obj];
        }
        return newDict;
    } else if ([self isKindOfClass:[NSSet class]]) {
        NSSet *oldSet = (NSSet *)self;
        NSMutableSet *newSet = [NSMutableSet set];
        for (id obj in oldSet) {
            [newSet addObject:[obj deepMutableCopy]];
        }
        return newSet;
#if MAKE_MUTABLE_COPIES_OF_NONCOLLECTION_OBJECTS
    } else if ([self conformsToProtocol:@protocol(NSMutableCopying)]) {
            // e.g. NSString
        return [self mutableCopy];
    } else if ([self conformsToProtocol:@protocol(NSCopying)]) {
            // e.g. NSNumber
        return [self copy];
#endif
    } else {
        return self;
    }
}
@end

Use it like

NSDictionary *dict = ...;
NSMutableDictionary *mdict = [dict deepMutableCopy];

(Dictionary keys are not copied, only the values).

I am quite sure that I have seen something like this on SO, but cannot find it right now.

Problem

I have an `NSDictionary` that contains instances of many different types objects (`NSArrays`, `NSDictionaries`, `NSStrings`, `NSNumbers`, etc...). Many of the `NSDictionaries` and `NSStrings` have their own nested `NSDictionaries` and `NSArrays`. How can I loop through the entire hierarchy, from top to bottom, and convert ALL instances of `NSDictionaries` and `NSArrays` to `NSMutableDictionaries` and `NSMutableArrays`, respectively? Is there any easy "recursively make mutable copies" function I'm unaware of? If not, do I just need to loop and type check repeatedly? Can I just replace as I go or do I have rebuild the entire hierarchy?

Original source