8

我有一个NSDictionary包含许多不同类型对象(NSArrays、、、、NSDictionariesNSStrings)的实例NSNumbers。许多NSDictionariesandNSStrings都有自己的嵌套NSDictionariesand NSArrays

如何从上到下遍历整个层次结构,并分别将 and 的所有实例转换为NSDictionariesand ?NSArraysNSMutableDictionariesNSMutableArrays

有没有我不知道的简单的“递归制作可变副本”功能?如果没有,我是否只需要反复循环和键入检查?我可以随时更换还是重建整个层次结构?

4

4 回答 4

18

以下方法创建嵌套数组、字典和集合的嵌套(深层)可变副本。它还可用于在层次结构内创建非集合对象的可变副本,例如字符串。

@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

像这样使用它

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

(不复制字典键,只复制值)。

我很确定我在 SO 上看到过类似的东西,但现在找不到。

于 2013-03-23T14:58:11.363 回答
2

虽然 Anoop 的答案很好(我认为,我也没有编译它),但如果您的实例层次结构实际上是一个属性列表,那么您可以使用NSPropertyListSerialization反序列化具有可变容器和/或叶节点的 plist。

这将减少到更少的代码行,并且可能比通过对象图手动下降更快,但只有当您最初从某个地方反序列化 plist 时,此解决方案才真正有意义。

于 2013-03-23T14:58:45.373 回答
1

对于外部 NSDictionary,这将创建 1 级向下。

您需要在一个方法中调用它,然后继续获取所有dictarray.

NSMutableDictionary *dict=[NSMutableDictionary new];
NSMutableArray *array=[NSMutableArray new];

for(NSDictionary *dict in yourMainDictionary){
   if([outerDict[dict] class]==[NSDictionary class]){
      [dict setObject:outerDict[dict] forKey:dict];
   }
   else if([outerDict[dict] class]==[NSArray class]){
      array[array.count]=outerDict[dict];
   }
}

没有编译器检查。读为算法

于 2013-03-23T14:12:30.887 回答
1

如果您使用某些操作系统方法来创建字典:这些方法通常具有允许您创建可变对象的参数。例如,JSON 序列化器类具有使所有字典和数组可变的标志,并使所有 NSString 对象可变(NSNumber 和 NSNull 永远不可变)。

于 2014-02-17T17:11:55.800 回答