如何使用嵌套数组/字典为NSArray和NSDictionary做真正的深度复制? [英] how to do true deep copy for NSArray and NSDictionary with have nested arrays/dictionary?

查看:133
本文介绍了如何使用嵌套数组/字典为NSArray和NSDictionary做真正的深度复制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:有没有办法使用现有的objective-c方法来完成NSDictionary或NSArray的完整深层副本,它们本身有嵌套的词典或数组?

Question: Is there a way to use existing objective-c methods to do a full deep copy of a NSDictionary or NSArray, that themselves have nested dictionaries or arrays within them?

这是我读过的问题可能是当它遇到嵌套字典或数组时,它只会将指针复制到嵌套项目,而不是真正复制项目。

That is I have read the problem may be when it hits a nested dictionary or array it only copies the pointer to the nested item, and not copy the item truely.

背景:作为一个例子,我试图用NSUserDefaults加载/保存以下配置,当加载需要转换不可变副本时,从NSUserDefault转到在进行更改之前可变。

Background: So as an example for me I'm trying to load/save the following config with NSUserDefaults and when loading need to convert the immutable copies one gets from NSUserDefault to mutable prior to making changes.


  • 项目( NSDictionary

    • 项目( NSDictionary

      • aString:NSString

      • aString2:NSString

      • aDate:NSDate

      • aDate2:NSDate

      • aBool:BOOL

      • aTI1: NSTimeInterval

      • aTI2:NSTimeInterval

      • 关键字( NSArray

        • keyword:NSString

        • 关键字:NSString

        • Items (NSDictionary)
          • Item (NSDictionary)
            • aString: NSString
            • aString2: NSString
            • aDate: NSDate
            • aDate2: NSDate
            • aBool: BOOL
            • aTI1: NSTimeInterval
            • aTI2: NSTimeInterval
            • Keywords (NSArray)
              • keyword: NSString
              • keyword: NSString

              推荐答案

              几年前,我写了一些类别方法完全相同的原因,将整个用户默认树转换为可变。他们在这里 - 使用它们需要您自担风险! : - )

              A couple of years ago, I wrote a few category methods for exactly the same reason, transforming a whole tree of user defaults to mutable. Here they are - use them at your own risk! :-)

              //
              //  SPDeepCopy.h
              //
              //  Created by Sherm Pendley on 3/15/09.
              //
              
              #import <Cocoa/Cocoa.h>
              
              // Deep -copy and -mutableCopy methods for NSArray and NSDictionary
              
              @interface NSArray (SPDeepCopy)
              
              - (NSArray*) deepCopy;
              - (NSMutableArray*) mutableDeepCopy;
              
              @end
              
              @interface NSDictionary (SPDeepCopy)
              
              - (NSDictionary*) deepCopy;
              - (NSMutableDictionary*) mutableDeepCopy;
              
              @end
              







              //
              //  SPDeepCopy.m
              //
              //  Created by Sherm Pendley on 3/15/09.
              //
              
              #import "SPDeepCopy.h"
              
              
              @implementation NSArray (SPDeepCopy)
              
              - (NSArray*) deepCopy {
                  unsigned int count = [self count];
                  id cArray[count];
              
                  for (unsigned int i = 0; i < count; ++i) {
                      id obj = [self objectAtIndex:i];
                      if ([obj respondsToSelector:@selector(deepCopy)])
                          cArray[i] = [obj deepCopy];
                      else
                          cArray[i] = [obj copy];
                  }
              
                  NSArray *ret = [[NSArray arrayWithObjects:cArray count:count] retain];
              
                  // The newly-created array retained these, so now we need to balance the above copies
                  for (unsigned int i = 0; i < count; ++i)
                      [cArray[i] release];
              
                  return ret;
              }
              - (NSMutableArray*) mutableDeepCopy {
                  unsigned int count = [self count];
                  id cArray[count];
              
                  for (unsigned int i = 0; i < count; ++i) {
                      id obj = [self objectAtIndex:i];
              
                      // Try to do a deep mutable copy, if this object supports it
                      if ([obj respondsToSelector:@selector(mutableDeepCopy)])
                          cArray[i] = [obj mutableDeepCopy];
              
                      // Then try a shallow mutable copy, if the object supports that
                      else if ([obj respondsToSelector:@selector(mutableCopyWithZone:)])
                          cArray[i] = [obj mutableCopy];
              
                      // Next try to do a deep copy
                      else if ([obj respondsToSelector:@selector(deepCopy)])
                          cArray[i] = [obj deepCopy];
              
                      // If all else fails, fall back to an ordinary copy
                      else
                          cArray[i] = [obj copy];
                  }
              
                  NSMutableArray *ret = [[NSMutableArray arrayWithObjects:cArray count:count] retain];
              
                  // The newly-created array retained these, so now we need to balance the above copies
                  for (unsigned int i = 0; i < count; ++i)
                      [cArray[i] release];
              
                  return ret;
              }
              
              @end
              
              @implementation NSDictionary (SPDeepCopy)
              
              - (NSDictionary*) deepCopy {
                  unsigned int count = [self count];
                  id cObjects[count];
                  id cKeys[count];
              
                  NSEnumerator *e = [self keyEnumerator];
                  unsigned int i = 0;
                  id thisKey;
                  while ((thisKey = [e nextObject]) != nil) {
                      id obj = [self objectForKey:thisKey];
              
                      if ([obj respondsToSelector:@selector(deepCopy)])
                          cObjects[i] = [obj deepCopy];
                      else
                          cObjects[i] = [obj copy];
              
                      if ([thisKey respondsToSelector:@selector(deepCopy)])
                          cKeys[i] = [thisKey deepCopy];
                      else
                          cKeys[i] = [thisKey copy];
              
                      ++i;
                  }
              
                  NSDictionary *ret = [[NSDictionary dictionaryWithObjects:cObjects forKeys:cKeys count:count] retain];
              
                  // The newly-created dictionary retained these, so now we need to balance the above copies
                  for (unsigned int i = 0; i < count; ++i) {
                      [cObjects[i] release];
                      [cKeys[i] release];
                  }
              
                  return ret;
              }
              - (NSMutableDictionary*) mutableDeepCopy {
                  unsigned int count = [self count];
                  id cObjects[count];
                  id cKeys[count];
              
                  NSEnumerator *e = [self keyEnumerator];
                  unsigned int i = 0;
                  id thisKey;
                  while ((thisKey = [e nextObject]) != nil) {
                      id obj = [self objectForKey:thisKey];
              
                      // Try to do a deep mutable copy, if this object supports it
                      if ([obj respondsToSelector:@selector(mutableDeepCopy)])
                          cObjects[i] = [obj mutableDeepCopy];
              
                      // Then try a shallow mutable copy, if the object supports that
                      else if ([obj respondsToSelector:@selector(mutableCopyWithZone:)])
                          cObjects[i] = [obj mutableCopy];
              
                      // Next try to do a deep copy
                      else if ([obj respondsToSelector:@selector(deepCopy)])
                          cObjects[i] = [obj deepCopy];
              
                      // If all else fails, fall back to an ordinary copy
                      else
                          cObjects[i] = [obj copy];
              
                      // I don't think mutable keys make much sense, so just do an ordinary copy
                      if ([thisKey respondsToSelector:@selector(deepCopy)])
                          cKeys[i] = [thisKey deepCopy];
                      else
                          cKeys[i] = [thisKey copy];
              
                      ++i;
                  }
              
                  NSMutableDictionary *ret = [[NSMutableDictionary dictionaryWithObjects:cObjects forKeys:cKeys count:count] retain];
              
                  // The newly-created dictionary retained these, so now we need to balance the above copies
                  for (unsigned int i = 0; i < count; ++i) {
                      [cObjects[i] release];
                      [cKeys[i] release];
                  }
              
                  return ret;
              }
              
              @end
              

              这篇关于如何使用嵌套数组/字典为NSArray和NSDictionary做真正的深度复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆