deep mutable copy of a NSMutableDictionary

前端 未结 8 1875
醉话见心
醉话见心 2020-11-30 00:55

I am trying to create a deep-copy of a NSMutableDictionary and assign it to another NSMutableDictionary. The dictionary contains a bunch of arrays, each array containing nam

相关标签:
8条回答
  • 2020-11-30 01:21

    Trying to figure out by checking respondToSelector(@selector(mutableCopy)) won't give the desired results as all NSObject-based objects respond to this selector (it's part of NSObject). Instead we have to query if an object conforms to NSMutableCopying or at least NSCopying. Here's my answer based on this gist mentioned in the accepted answer:

    For NSDictionary:

    @implementation NSDictionary (MutableDeepCopy)
    
    //  As seen here (in the comments): https://gist.github.com/yfujiki/1664847
    - (NSMutableDictionary *)mutableDeepCopy
    {
        NSMutableDictionary *returnDict = [[NSMutableDictionary alloc] initWithCapacity:self.count];
    
        NSArray *keys = [self allKeys];
    
        for(id key in keys) {
            id oneValue = [self objectForKey:key];
            id oneCopy = nil;
    
            if([oneValue respondsToSelector:@selector(mutableDeepCopy)]) {
                oneCopy = [oneValue mutableDeepCopy];
            } else if([oneValue conformsToProtocol:@protocol(NSMutableCopying)]) {
                oneCopy = [oneValue mutableCopy];
            } else if([oneValue conformsToProtocol:@protocol(NSCopying)]){
                oneCopy = [oneValue copy];
            } else {
                oneCopy = oneValue;
            }
    
            [returnDict setValue:oneCopy forKey:key];
        }
    
        return returnDict;
    }
    
    @end
    

    For NSArray:

    @implementation NSArray (MutableDeepCopy)
    
    - (NSMutableArray *)mutableDeepCopy
    {
        NSMutableArray *returnArray = [[NSMutableArray alloc] initWithCapacity:self.count];
    
        for(id oneValue in self) {
            id oneCopy = nil;
    
            if([oneValue respondsToSelector:@selector(mutableDeepCopy)]) {
                oneCopy = [oneValue mutableDeepCopy];
            } else if([oneValue conformsToProtocol:@protocol(NSMutableCopying)]) {
                oneCopy = [oneValue mutableCopy];
            } else if([oneValue conformsToProtocol:@protocol(NSCopying)]){
                oneCopy = [oneValue copy];
            } else {
                oneCopy = oneValue;
            }
    
            [returnArray addObject:oneCopy];
        }
    
        return returnArray;
    }
    
    @end
    

    Both methods have the same internal to-copy-or-not-to-copy logic and that could be extracted into a separate method but I left it like this for clarity.

    0 讨论(0)
  • 2020-11-30 01:24

    For ARC - note kCFPropertyListMutableContainersAndLeaves for truly deep mutability.

        NSMutableDictionary* mutableDict = (NSMutableDictionary *)
          CFBridgingRelease(
              CFPropertyListCreateDeepCopy(kCFAllocatorDefault, 
               (CFDictionaryRef)someNSDict, 
               kCFPropertyListMutableContainersAndLeaves));
    
    0 讨论(0)
提交回复
热议问题