如何创建 NSArray 的副本并在不影响原始 NSArray 的情况下更改它?
How to create copy of NSArray and change it without affection original NSArray?
我需要 NSArray
的副本来存储日期状态。我尝试使用 mytableCopy
,据我所知,它制作了独立于原始对象的副本。
当我对 mutableCopy
进行更改时,我也在原始数组中进行了更改。
为什么?
我的代码是:
_nsarr = [[NSArray alloc] initWithArray:inputArray];
_nsMraa= [NSMutableArray alloc];
_nsMraa = [_nsarr mutableCopy];
注意:两个数组都是我对象的属性。 inputArray
是输入参数,之后就不用了。
备注:一个对象是 NSArray
,另一个是 NSMutableArray
试试这个
_nsMraa = [[NSArray alloc]initWithArray:_nsarr copyItems:YES];
如果你需要一个真正的深拷贝,比如当你有一个数组的数组时,你可以归档然后取消归档集合,前提是内容都符合 NSCoding 协议。下面显示了此技术的示例。
真正的深拷贝
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject:oldArray]];
正如 Bharat 和 Milan 所暗示的,NSArray
是一个引用类型数组,它包含一个指针数组。调用 mutableCopy
将生成数组的浅表副本并使副本可变,原始数组仍然是不可变的。但是,mutableCopy
和 copy
都不会对数组的内容执行深层复制。可变或不可变的是数组,而不是数组中保存的对象的内容。
假设如下:
@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
要复制数组中包含的单个对象,您需要创建数组的 "deep" 副本,这意味着要(递归地)复制数组的内容以及数组本身。没有快速简便的方法来创建数组的深拷贝,因为它在很大程度上取决于您如何(如果?)对引用的对象进行深拷贝。 Bharat 提出了一种方法(由于它对对象进行序列化和反序列化,并且要求它们遵守 NSCoding
,因此成本略高)一种方法可能类似于:
_nsmarr = [NSArray withCapacity:[_nsarr count]];
for(MyObject* foo in _nsarr) {
[_nsmarr addObject:[foo copy]];
}
假设 foo 实现了 NSCopying
协议,这在本质上与 initWithArray:copyItems 相同:Milan 建议的方法:
_nsmarr = [[NSMutableArray alloc] initWithArray:_nsarr copyItems:YES];
我需要 NSArray
的副本来存储日期状态。我尝试使用 mytableCopy
,据我所知,它制作了独立于原始对象的副本。
当我对 mutableCopy
进行更改时,我也在原始数组中进行了更改。
为什么?
我的代码是:
_nsarr = [[NSArray alloc] initWithArray:inputArray];
_nsMraa= [NSMutableArray alloc];
_nsMraa = [_nsarr mutableCopy];
注意:两个数组都是我对象的属性。 inputArray
是输入参数,之后就不用了。
备注:一个对象是 NSArray
,另一个是 NSMutableArray
试试这个
_nsMraa = [[NSArray alloc]initWithArray:_nsarr copyItems:YES];
如果你需要一个真正的深拷贝,比如当你有一个数组的数组时,你可以归档然后取消归档集合,前提是内容都符合 NSCoding 协议。下面显示了此技术的示例。
真正的深拷贝
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];
正如 Bharat 和 Milan 所暗示的,NSArray
是一个引用类型数组,它包含一个指针数组。调用 mutableCopy
将生成数组的浅表副本并使副本可变,原始数组仍然是不可变的。但是,mutableCopy
和 copy
都不会对数组的内容执行深层复制。可变或不可变的是数组,而不是数组中保存的对象的内容。
假设如下:
@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
要复制数组中包含的单个对象,您需要创建数组的 "deep" 副本,这意味着要(递归地)复制数组的内容以及数组本身。没有快速简便的方法来创建数组的深拷贝,因为它在很大程度上取决于您如何(如果?)对引用的对象进行深拷贝。 Bharat 提出了一种方法(由于它对对象进行序列化和反序列化,并且要求它们遵守 NSCoding
,因此成本略高)一种方法可能类似于:
_nsmarr = [NSArray withCapacity:[_nsarr count]];
for(MyObject* foo in _nsarr) {
[_nsmarr addObject:[foo copy]];
}
假设 foo 实现了 NSCopying
协议,这在本质上与 initWithArray:copyItems 相同:Milan 建议的方法:
_nsmarr = [[NSMutableArray alloc] initWithArray:_nsarr copyItems:YES];