如何使用嵌套数组/字典为NSArray和NSDictionary做真正的深度复制? [英] how to do true deep copy for NSArray and NSDictionary with have nested arrays/dictionary?
问题描述
问题:有没有办法使用现有的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屋!
- Item (NSDictionary)
- 项目( NSDictionary )