Ios 如何创建NSArray副本并在不影响原始NSArray的情况下对其进行更改?

Ios 如何创建NSArray副本并在不影响原始NSArray的情况下对其进行更改?,ios,objective-c,copy,nsarray,Ios,Objective C,Copy,Nsarray,我需要一份NSArray的副本来存储日期状态。我尝试使用mytableCopy,据我所知,它是独立于原始对象的复制 当我对mutableCopy进行更改时,原始数组中也发生了更改 为什么? 我的代码是: _nsarr = [[NSArray alloc] initWithArray:inputArray]; _nsMraa= [NSMutableArray alloc]; _nsMraa = [_nsarr mutableCopy]; 注意:两个数组都是我的对象的属性inputArray是输入

我需要一份
NSArray
的副本来存储日期状态。我尝试使用
mytableCopy
,据我所知,它是独立于原始对象的复制

当我对
mutableCopy
进行更改时,原始数组中也发生了更改

为什么?

我的代码是:

_nsarr = [[NSArray alloc] initWithArray:inputArray];
_nsMraa= [NSMutableArray alloc];
_nsMraa = [_nsarr mutableCopy];
注意:两个数组都是我的对象的属性
inputArray
是输入参数,之后不再使用

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

试试这个

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

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

如果您需要真正的深度拷贝,例如当您有一个阵列阵列时,您可以归档然后取消归档集合,前提是所有内容都符合NSCoding协议。下面显示了该技术的一个示例

  • 真正的深度复制品

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

如果您需要真正的深度拷贝,例如当您拥有阵列阵列时,您可以归档然后取消归档集合,前提是内容都符合NSCoding协议。下面显示了该技术的一个示例

  • 真正的深度复制品

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

正如巴拉特和米兰所提到的,
NSArray
是一个引用类型数组,它包含一个指针数组。调用
mutableCopy
将创建数组的浅层副本并使副本可变,但原始副本仍然不可更改。但是,
mutableCopy
copy
都不会对数组的内容执行深度复制。是数组变了还是变了,而不是数组中对象的内容

假设:

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

...

_nsarr = [NSArray arrayWithObject:[[MyObject alloc] initWithState]];
_nsmarr = [_nsarr mutableCopy];
此时,您有两个不同的数组,
\u nsarr
\u nsmarr
,一个是不可变的,另一个是
\u nsarr[0]
\u nsmarr[0]
仍然是相同的对象,这意味着
[\u nsarr[0]setState:1]
是有效的,并且它与
[u nsmarr]具有完全相同的效果[0]设置状态: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];

正如Bharat和Milan所提到的,
NSArray
是一个引用类型数组,它包含一个指针数组。调用
mutableCopy
将创建数组的浅拷贝并使拷贝可变,原始拷贝仍然是不可更改的。无论
mutableCopy
还是
copy
都不会在然而,数组的内容是可变的还是不可变的,而不是数组中保存的对象的内容

假设:

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

...

_nsarr = [NSArray arrayWithObject:[[MyObject alloc] initWithState]];
_nsmarr = [_nsarr mutableCopy];
此时,您有两个不同的数组,
\u nsarr
\u nsmarr
,一个是不可变的,另一个是
\u nsarr[0]
\u nsmarr[0]
仍然是相同的对象,这意味着
[\u nsarr[0]setState:1]
是有效的,并且它与
[u nsmarr]具有完全相同的效果[0]设置状态: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];

\u nsMraa
NSMutableArray
。您将其定义为
NSArray
。我需要可变对象,这样我就可以更改状态。我需要不可变对象,这样我就可以检查原始状态是否有更改。如果我有3个状态(0、1和2)我将状态2作为初始状态,我可以将其更改为0,这样会有差异,但如果我再更改2次,它将再次为2,并且不会有任何差异。哦,对不起,我不知何故错误地将其理解为NSArray,我认为David answer适用于您。10倍,对于答案,我投了赞成票,因为这是一个好的解决方案。问题是我收到了一些错误。我使用最“愚蠢”的方法向新数组添加新元素。
\u nsMraa
NSMutableArray
。您将其定义为
NSArray
。我需要可变对象,这样我就可以更改状态。我需要不可变对象,这样我就可以检查原始数组是否有更改。如果我有3种状态(0、1和2)我将状态2作为初始状态,我可以将其更改为0,这样会有差异,但如果我再更改2次,它将再次为2,并且不会有任何差异。哦,对不起,我不知何故错误地将其理解为NSArray,我认为David answer适用于您。10倍,对于答案,我投了赞成票,因为这是一个好的解决方案。问题是我收到了一些错误。我使用最“愚蠢”的方法将新元素添加到新数组中。请注意,行
\u nsMraa=[NSMutableArray alloc];
没有做任何事情,因为您在下面的步骤中覆盖了它。10x对于备注@DavidBerryNote,行
\u nsMraa=[NSMutableArray alloc];
没有做任何事情,因为您覆盖了它