当前位置:  开发笔记 > IOS > 正文

深度复制NSArray

如何解决《深度复制NSArray》经验,为你挑选了4个好方法。

是否有任何内置功能可以让我深层复制NSMutableArray

我环顾四周,有些人说[aMutableArray copyWithZone:nil]是深刻的副本.但我试过,它似乎是一个浅薄的副本.

现在我用for循环手动执行复制:

//deep copy a 9*9 mutable array to a passed-in reference array

-deepMuCopy : (NSMutableArray*) array 
    toNewArray : (NSMutableArray*) arrayNew {

    [arrayNew removeAllObjects];//ensure it's clean

    for (int y = 0; y<9; y++) {
        [arrayNew addObject:[NSMutableArray new]];
        for (int x = 0; x<9; x++) {
            [[arrayNew objectAtIndex:y] addObject:[NSMutableArray new]];

            NSMutableArray *aDomain = [[array objectAtIndex:y] objectAtIndex:x];
            for (int i = 0; i<[aDomain count]; i++) {

                //copy object by object
                NSNumber* n = [NSNumber numberWithInt:[[aDomain objectAtIndex:i] intValue]];
                [[[arrayNew objectAtIndex:y] objectAtIndex:x] addObject:n];
            }
        }
    }
}

但我想要一个更清洁,更简洁的解决方案.



1> François P...:

正如Apple文档所述,

如果您只需要一个级别深的副本,您可以明确地要求一个...

NSMutableArray *newArray = [[NSMutableArray alloc] 
                             initWithArray:oldArray copyItems:YES];

上面的代码创建了一个新数组,其成员是旧数组成员的浅表副本.

请注意,如果您需要深度复制整个嵌套数据结构 - 链接的Apple文档称之为"真正的深层副本" - 那么这种方法是不够的 - 请参阅此处的其他答案.


这是一个不完整的答案.这导致一级深拷贝.如果Array中有更复杂的类型,它将不提供深层复制.
我不认为这会按预期工作.来自Apple文档:"copyWithZone:方法执行*浅拷贝*.如果你有一个任意深度的集合,为flag参数传递YES将执行表面下第一级的不可变副本.如果你传递NO第一级的可变性不受影响.*在任何一种情况下,所有更深层次的可变性都不受影响.*"SO问题涉及深度可变副本.
这个*可以是一个深层副本,具体取决于接收类上如何实现`copyWithZone:`.
这不是一个深刻的副本

2> Andrew Grant..:

我知道轻松做到这一点的唯一方法是归档,然后立即取消归档你的数组.这感觉有点像黑客,但实际上在Apple文档中明确建议复制集合,其中指出:

如果您需要真正的深层副本,例如当您拥有阵列数组时,只要内容全部符合NSCoding协议,您就可以归档然后取消归档该集合.清单3显示了这种技术的一个例子.

清单3真正的深层副本

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
          [NSKeyedArchiver archivedDataWithRootObject:oldArray]];

问题是您的对象必须支持NSCoding接口,因为这将用于存储/加载数据.

Swift 2版本:

let trueDeepCopyArray = NSKeyedUnarchiver.unarchiveObjectWithData(
    NSKeyedArchiver.archivedDataWithRootObject(oldArray))


如果阵列很大,使用NSArchiver和NSUnarchiver是性能非常高的解决方案.编写使用NSCopying协议的通用NSArray类别方法可以实现这一目的,从而导致对不可变对象的简单"保留"以及可变对象的真正"复制".

3> Cameron Lowe..:

默认情况下复制会生成浅表副本

这是因为调用与使用默认区域进行复制copy相同copyWithZone:NULL.该copy调用不会导致深层复制.在大多数情况下,它会给你一个浅的副本,但无论如何它取决于类.有关详细讨论,我建议Apple Developer站点上的Collections Programming Topics.

initWithArray:CopyItems:提供一个级别的深层副本

NSArray *deepCopyArray = [[NSArray alloc] initWithArray:someArray copyItems:YES];

NSCoding 是Apple推荐的提供深层复制的方式

对于真正的深层副本(数组),您将需要NSCoding并归档/取消归档对象:

NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];



4> Darshit Shah..:

对于Dictonary

NSMutableDictionary *newCopyDict = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)objDict, kCFPropertyListMutableContainers);

对于数组

NSMutableArray *myMutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(NULL, arrData, kCFPropertyListMutableContainersAndLeaves);

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有