Objective-C:复制数组,只修改拷贝中的元素(对象)

时间:2021-03-21 20:19:51

I've read through many SO posts before asking this question and I'm guessing this answer was in there somewhere, but I didn't see it. I'm new to Objective-C and I'm trying to do a (seemingly) simple action that I can't figure out.

在问这个问题之前,我读了很多文章,我猜答案就在那里,但我没看到。我是Objective-C的新手,我想做一个(看起来)很简单的动作,但我做不出来。

The general idea is that I have an NSArray filled with objects (specifically of type UIImageView). I want to copy that array, which I've done a number of ways (all successful).

一般的想法是我有一个满是对象的NSArray(特别是类型为UIImageView)。我想复制这个数组,我已经做了很多次(都成功了)。

After a copy it, I now have two arrays. I want to modify an object, say at index 2, ONLY in the copy.

复制之后,我现在有两个数组。我想修改一个对象,比如索引2,只在拷贝中。

So far it seems like, because the copy is merely copying the reference (or pointer), changing the object at index 2 will change it in both the copy and the original.

到目前为止,由于复制仅仅是复制引用(或指针),所以在索引2处修改对象将在复制和原始中修改它。

Does that make sense?

这说得通吗?

NSArray *originalArray = @[object1, object2];

Ways I've tried copying this array, so that I can achieve what I want:

我尝试复制这个数组,这样我就可以实现我想要的:

NSMutableArray *originalArrayCopy = [NSMutableArray arrayWithArray:originalArray];

NSArray *originalArrayCopy = [originalArray copy];

NSMutableArray *originalArrayCopy = [[NSMutableArray alloc] initWithArray:originalArray];

And it seems that in each case, modifying an object from the copy also modifies it in the original.

似乎在每种情况下,从副本中修改一个对象也会在原始版本中修改它。

NOTE: While NSArray is obviously immutable, the objects within my original array are mutable.

注意:虽然NSArray显然是不可变的,但我原始数组中的对象是可变的。

4 个解决方案

#1


9  

If the elements of your array conform to the NSCopying protocol, you can do this:

如果数组的元素符合NSCopying协议,您可以这样做:

NSMutableArray *copy = [[NSMutableArray alloc] initWithArray:originalArray copyItems:YES];

This has the effect of sending copy to each element of the original array, storing the copies in the new array.

这可以将副本发送到原始数组的每个元素,并将副本存储在新的数组中。

This is fine if each element returns a new, mutable copy when it receives the copy message. However, several Foundation classes (like NSMutableArray and NSMutableString) return immutable copies when they receive the copy message. If your elements belong to such a class, you need to send the mutableCopy message instead.

如果每个元素在接收到复制消息时返回一个新的、可变的副本,那么这是可以的。然而,一些基础类(比如NSMutableArray和NSMutableString)在收到复制消息时返回不可变的副本。如果您的元素属于这样的类,则需要发送mutableCopy消息。

There's no built-in public message to do that. You can do it manually like this:

这样做没有内置的公共信息。你可以这样手动操作:

NSMutableArray *copy = [[NSMutableArray alloc] initWithCapacity:originalArray.count];
for (id element in originalArray) {
    [copy addObject:[element mutableCopy]];
}

#2


1  

This makes a deep copy of the first NSArray into a Second NSMutableArray:

这使得第一个NSArray的深度拷贝变成第二个NSMutableArray:

NSArray *firstArray = [NSArray arrayWithObjects:@"foo", @"bar",nil];
NSMutableArray *secondArray = [[NSMutableArray alloc]initWithArray:firstArray copyItems:YES];

#3


1  

As long as objects you're going to copy implement the NSCoding protocol

只要对象被复制,就会实现NSCoding协议

(void)encodeWithCoder:(NSCoder *)encoder;
(id)initWithCoder:(NSCoder *)decoder;

you could make a deep copy of any object in this way

你可以用这种方法复制任何物体。

NSArray *originalArray = @[object1, object2];
NSMutableArray *deepCopy = [NSkeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject: originalArray]];

#4


0  

Yes, all that would copy the array only. Your copied array will still refer to the same objects.

是的,所有这些都将只复制数组。复制的数组仍然引用相同的对象。

I don't think (or just don't know how) that you can copy all contained objects in one go. I guess that you would have to iterate through the objects in the original array, copy each object and add its copy to a newly created and originally empty mutable array. How these objects are to be copied depends very much on the nature of these objects and on the purpose for copying them.

我不认为(或者只是不知道如何)您可以一次复制所有包含的对象。我猜您将不得不遍历原始数组中的对象,复制每个对象并将其副本添加到新创建的、最初为空的可变数组中。如何复制这些对象在很大程度上取决于这些对象的性质和复制它们的目的。

And yes, there is no reason why the objects within an immutable array should be immutable too.

是的,不可变数组中的对象也应该是不可变的,这是没有理由的。

#1


9  

If the elements of your array conform to the NSCopying protocol, you can do this:

如果数组的元素符合NSCopying协议,您可以这样做:

NSMutableArray *copy = [[NSMutableArray alloc] initWithArray:originalArray copyItems:YES];

This has the effect of sending copy to each element of the original array, storing the copies in the new array.

这可以将副本发送到原始数组的每个元素,并将副本存储在新的数组中。

This is fine if each element returns a new, mutable copy when it receives the copy message. However, several Foundation classes (like NSMutableArray and NSMutableString) return immutable copies when they receive the copy message. If your elements belong to such a class, you need to send the mutableCopy message instead.

如果每个元素在接收到复制消息时返回一个新的、可变的副本,那么这是可以的。然而,一些基础类(比如NSMutableArray和NSMutableString)在收到复制消息时返回不可变的副本。如果您的元素属于这样的类,则需要发送mutableCopy消息。

There's no built-in public message to do that. You can do it manually like this:

这样做没有内置的公共信息。你可以这样手动操作:

NSMutableArray *copy = [[NSMutableArray alloc] initWithCapacity:originalArray.count];
for (id element in originalArray) {
    [copy addObject:[element mutableCopy]];
}

#2


1  

This makes a deep copy of the first NSArray into a Second NSMutableArray:

这使得第一个NSArray的深度拷贝变成第二个NSMutableArray:

NSArray *firstArray = [NSArray arrayWithObjects:@"foo", @"bar",nil];
NSMutableArray *secondArray = [[NSMutableArray alloc]initWithArray:firstArray copyItems:YES];

#3


1  

As long as objects you're going to copy implement the NSCoding protocol

只要对象被复制,就会实现NSCoding协议

(void)encodeWithCoder:(NSCoder *)encoder;
(id)initWithCoder:(NSCoder *)decoder;

you could make a deep copy of any object in this way

你可以用这种方法复制任何物体。

NSArray *originalArray = @[object1, object2];
NSMutableArray *deepCopy = [NSkeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject: originalArray]];

#4


0  

Yes, all that would copy the array only. Your copied array will still refer to the same objects.

是的,所有这些都将只复制数组。复制的数组仍然引用相同的对象。

I don't think (or just don't know how) that you can copy all contained objects in one go. I guess that you would have to iterate through the objects in the original array, copy each object and add its copy to a newly created and originally empty mutable array. How these objects are to be copied depends very much on the nature of these objects and on the purpose for copying them.

我不认为(或者只是不知道如何)您可以一次复制所有包含的对象。我猜您将不得不遍历原始数组中的对象,复制每个对象并将其副本添加到新创建的、最初为空的可变数组中。如何复制这些对象在很大程度上取决于这些对象的性质和复制它们的目的。

And yes, there is no reason why the objects within an immutable array should be immutable too.

是的,不可变数组中的对象也应该是不可变的,这是没有理由的。