在问这个问题之前,我已经阅读了很多SO帖子,我猜这个答案就在那里,但我没有看到。我是Objective-C的新手,我正试图做一个(看似)简单的动作,我无法弄明白。
一般的想法是我有NSArray
填充了对象(特别是类型UIImageView
)。我想要复制那个数组,我已经做了很多种方式(都成功了)。
复制后,我现在有两个数组。我想修改一个对象,比如在副本中的索引2, ONLY 。
到目前为止,似乎是因为副本只是复制引用(或指针),更改索引2处的对象将在副本和中更改它原来。
这有意义吗?
NSArray *originalArray = @[object1, object2];
我尝试复制这个数组的方式,这样我就能实现我想要的目标:
NSMutableArray *originalArrayCopy = [NSMutableArray arrayWithArray:originalArray];
NSArray *originalArrayCopy = [originalArray copy];
NSMutableArray *originalArrayCopy = [[NSMutableArray alloc] initWithArray:originalArray];
似乎在每种情况下,从副本修改对象也会在原始文件中修改它。
注意:虽然NSArray
显然是不可变的,但我原始数组中的对象是可变的。
答案 0 :(得分:11)
如果数组的元素符合NSCopying
协议,则可以执行以下操作:
NSMutableArray *copy = [[NSMutableArray alloc] initWithArray:originalArray copyItems:YES];
这样可以将copy
发送到原始数组的每个元素,并将副本存储在新数组中。
如果每个元素在收到copy
消息时返回一个新的可变副本,那么这很好。但是,一些Foundation类(如NSMutableArray
和NSMutableString
)在收到copy
消息时会返回不可变副本。如果您的元素属于这样的类,则需要发送mutableCopy
消息。
没有内置的公共消息可以做到这一点。你可以像这样手动完成:
NSMutableArray *copy = [[NSMutableArray alloc] initWithCapacity:originalArray.count];
for (id element in originalArray) {
[copy addObject:[element mutableCopy]];
}
答案 1 :(得分:1)
这会将第一个NSArray的深层副本转换为第二个NSMutableArray:
NSArray *firstArray = [NSArray arrayWithObjects:@"foo", @"bar",nil];
NSMutableArray *secondArray = [[NSMutableArray alloc]initWithArray:firstArray copyItems:YES];
答案 2 :(得分:1)
只要您要复制的对象实现NSCoding协议
(void)encodeWithCoder:(NSCoder *)encoder;
(id)initWithCoder:(NSCoder *)decoder;
你可以用这种方式制作任何对象的深层副本
NSArray *originalArray = @[object1, object2];
NSMutableArray *deepCopy = [NSkeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject: originalArray]];
答案 3 :(得分:0)
是的,所有这些只会复制数组。复制的数组仍将引用相同的对象。
我不认为(或者只是不知道如何)你可以一次性复制所有包含的对象。我想你必须遍历原始数组中的对象,复制每个对象并将其副本添加到新创建的并且最初为空的可变数组中。 如何复制这些对象在很大程度上取决于这些对象的性质以及复制它们的目的。
是的,没有理由为什么不可变数组中的对象也应该是不可变的。