如何创建NSArray的副本并更改它没有感情原始的NSArray?

时间:2016-03-14 13:06:17

标签: ios objective-c copy nsarray

我需要NSArray的副本来存储日期状态。我尝试使用我理解的mytableCopy制作独立于原始对象的副本。

当我对mutableCopy进行更改时,我在原始数组中也有更改。

为什么?

我的代码是:

_nsarr = [[NSArray alloc] initWithArray:inputArray];
_nsMraa= [NSMutableArray alloc];
_nsMraa = [_nsarr mutableCopy];

注意:两个数组都是我的对象的属性。 inputArray是输入参数,之后不再使用。

备注:一个对象为NSArray,另一个为NSMutableArray

3 个答案:

答案 0 :(得分:2)

正如Bharat和Milan所提到的,NSArray是一个引用类型数组,它包含一个指针数组。调用mutableCopy将生成数组的浅表副本并使副本可变,原始仍然是不可变的。但是mutableCopycopy都不会对数组的CONTENTS执行深层复制。 ARRAY是否变得可变,而不是数组中保存的对象的内容。

假设如下:

@interface MyObject
- (int) state;
- (void) setState:(int) state;
@end

...

_nsarr = [NSArray arrayWithObject:[[MyObject alloc] initWithState]];
_nsmarr = [_nsarr mutableCopy];

此时你有两个不同的数组,_nsarr_nsmarr,一个不可变,一个是,_nsarr[0]_nsmarr[0]仍然是同一个对象,这意味着[_nsarr[0] setState:1]有效,并且它与[_nsmarr[0] setState:1]具有完全相同的效果

[_nsarr[0] setState:1];
NSLog("%d", [_nsmarr[0] state]);   // ==> 1

[_nsarr[0] setState:2];
NSLog("%d", [_nsmarr[0] state]);   // ==> 2

要复制数组中包含的各个对象,需要创建数组的“深层”副本,这意味着要复制数组的内容(递归)以及数组本身。没有快速简便的方法来创建数组的深层副本,因为它很大程度上取决于如何(如果?)您可以对引用的对象进行深层复制。 Bharat提出了一种方法(由于它对对象进行序列化和反序列化,并且要求它们遵守NSCoding),因此成本很高:一种方法可能类似于:

_nsmarr = [NSArray withCapacity:[_nsarr count]];
for(MyObject* foo in _nsarr) {
    [_nsmarr addObject:[foo copy]];
}

假设foo实现了NSCopying协议,这基本上与米兰建议的initWithArray:copyItems:方法相同:

_nsmarr = [[NSMutableArray alloc] initWithArray:_nsarr copyItems:YES];

答案 1 :(得分:1)

试试这个

_nsMraa = [[NSArray alloc]initWithArray:_nsarr copyItems:YES];

答案 2 :(得分:0)

如果您需要真正的深层拷贝,例如当您拥有阵列数组时,只要内容全部符合NSCoding协议,您就可以归档然后取消归档该集合。这种技术的一个例子如下所示。

  • 真正的深层复制

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