copy 和 mutableCopy 如何应用于 NSArray 和 NSMutableArray?

发布于 2024-08-16 09:21:40 字数 840 浏览 5 评论 0原文

NSArrayNSMutableArray 上使用时,copymutableCopy 有什么区别?

这是我的理解;这是正确的吗?

// ** NSArray **
NSArray *myArray_imu = [NSArray  arrayWithObjects:@"abc", @"def", nil];

// No copy, increments retain count, result is immutable
NSArray *myArray_imuCopy = [myArray_imu copy];

// Copys object, result is mutable 
NSArray *myArray_imuMuta = [myArray_imu mutableCopy];

// Both must be released later

// ** NSMutableArray **
NSMutableArray *myArray_mut = [NSMutableArray arrayWithObjects:@"A", @"B", nil];

// Copys object, result is immutable
NSMutableArray *myArray_mutCopy = [myArray_mut copy];

// Copys object, result is mutable
NSMutableArray *myArray_mutMuta = [myArray_mut mutableCopy];

// Both must be released later

What is the difference between copy and mutableCopy when used on either an NSArray or an NSMutableArray?

This is my understanding; is it correct?

// ** NSArray **
NSArray *myArray_imu = [NSArray  arrayWithObjects:@"abc", @"def", nil];

// No copy, increments retain count, result is immutable
NSArray *myArray_imuCopy = [myArray_imu copy];

// Copys object, result is mutable 
NSArray *myArray_imuMuta = [myArray_imu mutableCopy];

// Both must be released later

// ** NSMutableArray **
NSMutableArray *myArray_mut = [NSMutableArray arrayWithObjects:@"A", @"B", nil];

// Copys object, result is immutable
NSMutableArray *myArray_mutCopy = [myArray_mut copy];

// Copys object, result is mutable
NSMutableArray *myArray_mutMuta = [myArray_mut mutableCopy];

// Both must be released later

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

再浓的妆也掩不了殇 2024-08-23 09:21:40

copymutableCopy 是在不同的协议中定义的(分别是 NSCopyingNSMutableCopying),以及 NSArray< /code> 两者都符合。 mutableCopy 是为 NSArray (不仅仅是 NSMutableArray)定义的,它允许您为原始不可变数组创建可变副本:

// create an immutable array
NSArray *arr = [NSArray arrayWithObjects: @"one", @"two", @"three", nil ];

// create a mutable copy, and mutate it
NSMutableArray *mut = [arr mutableCopy];
[mut removeObject: @"one"];

摘要:

  • 您可以依赖无论原始类型如何,mutableCopy 的结果都是可变的。对于数组,结果应该是 NSMutableArray
  • 不能依赖于copy的结果是可变的! copyNSMutableArray可能返回一个NSMutableArray,因为那是原始类,但是copying 任何任意 NSArray 实例都不会。

编辑:根据 Mark Bessey 的回答重新阅读原始代码。当您创建数组的副本时,当然您仍然可以修改原始数组,无论您如何处理该副本。 copymutableCopy 会影响新数组是否可变。

编辑 2:修正了我的(错误)假设,即 NSMutableArray -copy 将返回 NSMutableArray

copy and mutableCopy are defined in different protocols (NSCopying and NSMutableCopying, respectively), and NSArray conforms to both. mutableCopy is defined for NSArray (not just NSMutableArray) and allows you to make a mutable copy of an originally immutable array:

// create an immutable array
NSArray *arr = [NSArray arrayWithObjects: @"one", @"two", @"three", nil ];

// create a mutable copy, and mutate it
NSMutableArray *mut = [arr mutableCopy];
[mut removeObject: @"one"];

Summary:

  • you can depend on the result of mutableCopy to be mutable, regardless of the original type. In the case of arrays, the result should be an NSMutableArray.
  • you cannot depend on the result of copy to be mutable! copying an NSMutableArray may return an NSMutableArray, since that's the original class, but copying any arbitrary NSArray instance would not.

Edit: re-read your original code in light of Mark Bessey's answer. When you create a copy of your array, of course you can still modify the original regardless of what you do with the copy. copy vs mutableCopy affects whether the new array is mutable.

Edit 2: Fixed my (false) assumption that NSMutableArray -copy would return an NSMutableArray.

盗心人 2024-08-23 09:21:40

我认为您一定误解了 copy 和 mutableCopy 的工作原理。在第一个示例中,myArray_COPY 是 myArray 的不可变副本。复制后,您可以操作原始 myArray 的内容,而不影响 myArray_COPY 的内容。

在第二个示例中,您创建了 myArray 的可变副本,这意味着您可以修改数组的任一副本,而不会影响另一个副本。

如果我更改第一个示例以尝试从 myArray_COPY 插入/删除对象,则会失败,正如您所期望的那样。


也许思考一个典型的用例会有所帮助。通常情况下,您可能会编写一个接受 NSArray * 参数的方法,并基本上存储它以供以后使用。你可以这样做:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects retain];
}

...但是你会遇到一个问题,即可以使用 NSMutableArray 作为参数来调用该方法。创建数组的代码可能会在调用 doStuffLaterWith: 方法和稍后需要使用该值之间对其进行操作。在多线程应用程序中,数组的内容甚至可能在迭代数组时发生更改,这可能会导致一些有趣的错误。

如果您这样做:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects copy];
}

...那么副本将在调用该方法时创建数组内容的快照。

I think you must have misinterpreted how copy and mutableCopy work. In your first example, myArray_COPY is an immutable copy of myArray. Having made the copy, you can manipulate the contents of the original myArray, and not affect the contents of myArray_COPY.

In the second example, you create a mutable copy of myArray, which means that you can modify either copy of the array, without affecting the other.

If I change the first example to try to insert/remove objects from myArray_COPY, it fails, just as you'd expect.


Perhaps thinking about a typical use-case would help. It's often the case that you might write a method that takes an NSArray * parameter, and basically stores it for later use. You could do this this way:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects retain];
}

...but then you have the problem that the method can be called with an NSMutableArray as the argument. The code that created the array may manipulate it between when the doStuffLaterWith: method is called, and when you later need to use the value. In a multi-threaded app, the contents of the array could even be changed while you're iterating over it, which can cause some interesting bugs.

If you instead do this:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects copy];
}

..then the copy creates a snapshot of the contents of the array at the time the method is called.

情痴 2024-08-23 09:21:40

“copy”方法返回通过实现 NSCopying 协议 copyWithZone 创建的对象:

如果向 NSString 发送复制消息:

NSString* myString;

NSString* newString = [myString copy];

返回值将是一个 NSString (不可变)


mutableCopy 方法返回通过实现 NSMutableCopying 协议的 mutableCopyWithZone 创建的对象:

通过发送:

NSString* myString;

NSMutableString* newString = [myString mutableCopy];

返回值将会是可变的。


在所有情况下,该对象必须实现该协议,这意味着它将创建新的副本对象并将其返回给您。


对于 NSArray 来说,浅复制和深复制有额外的复杂性。

NSArray 的浅拷贝只会复制对原始数组对象的引用并将它们放入新数组中。

结果是:

NSArray* myArray;

NSMutableArray* anotherArray = [myArray mutableCopy];

[[anotherArray objectAtIndex:0] doSomething];

也会影响原始数组中索引 0 处的对象。


深层复制实际上会复制数组中包含的各个对象。这是通过向每个单独的对象发送“copyWithZone:”消息来完成的。

NSArray* myArray;

NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray
                                                       copyItems:YES];

编辑以消除我对可变对象复制的错误假设

The "copy" method returns the object created by implementing NSCopying protocols copyWithZone:

If you send NSString a copy message:

NSString* myString;

NSString* newString = [myString copy];

The return value will be an NSString (not mutable)


The mutableCopy method returns the object created by implementing NSMutableCopying protocol's mutableCopyWithZone:

By sending:

NSString* myString;

NSMutableString* newString = [myString mutableCopy];

The return value WILL be mutable.


In all cases, the object must implement the protocol, signifying it will create the new copy object and return it to you.


In the case of NSArray there is an extra level of complexity regarding shallow and deep copying.

A shallow copy of an NSArray will only copy the references to the objects of the original array and place them into the new array.

The result being that:

NSArray* myArray;

NSMutableArray* anotherArray = [myArray mutableCopy];

[[anotherArray objectAtIndex:0] doSomething];

Will also affect the object at index 0 in the original array.


A deep copy will actually copy the individual objects contained in the array. This done by sending each individual object the "copyWithZone:" message.

NSArray* myArray;

NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray
                                                       copyItems:YES];

Edited to remove my wrong assumption about mutable object copying

无畏 2024-08-23 09:21:40
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
                                                           copyItems:YES];

将创建 anotherArray,它是 oldArray 的副本,深度为 2 层。如果 oldArray 的对象是一个数组。大多数应用中通常都是这种情况。

好吧,如果我们需要一个真正的深度复制,我们可以使用,

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

这将确保所有级别实际上都被复制,并保留每个级别的原始对象的可变性。

罗伯特·克拉伦斯·达尔梅达​​,
印度班加罗尔。

NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
                                                           copyItems:YES];

will create anotherArray which is a copy of oldArray to 2 levels deep. If an object of oldArray is an Array. Which is generally the case in most applications.

Well if we need a True Deep Copy we could use,

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

This would ensure that all levels are actually copied retaining the mutability of the original object at each level.

Robert Clarence D'Almeida,
Bangalore, India.

失去的东西太少 2024-08-23 09:21:40

您正在原始数组上调用 addObject 和 removeObjectAtIndex ,而不是您创建的新副本。调用 copy 与 mutableCopy 只会影响对象的新副本的可变性,而不影响原始对象。

You're calling addObject and removeObjectAtIndex on the original array, rather than the new copy of it you've made. Calling copy vs mutableCopy only effects the mutability of the new copy of the object, not the original object.

时光无声 2024-08-23 09:21:40

简单来说,

  • copy 返回一个不可变(不能修改)的数组副本,
  • mutableCopy 返回一个可变(可以修改)的数组副本。

复制(在这两种情况下)意味着您获得一个新数组,其中“填充”了对原始数组的对象引用(即在副本中引用相同(原始)对象。

如果将新对象添加到 mutableCopy,则它们是唯一的如果从 mutableCopy 中删除对象,则

在这两种情况下都会将其视为原始数组在创建副本时的快照。

To state it simply,

  • copy returns an immutable (can't be modified) copy of the array,
  • mutableCopy returns a mutable (can be modified) copy of the array.

Copy (in both cases) means that you get a new array "populated" with object references to the original array (i.e. the same (original) objects are referenced in the copies.

If you add new objects to the mutableCopy, then they are unique to the mutableCopy. If you remove objects from the mutableCopy, they are removed from the original array.

Think of the copy in both cases, as a snapshot in time of the original array at the time the copy was created.

你的他你的她 2024-08-23 09:21:40

假设

NSArray *A = xxx; // A with three NSDictionary objects
NSMutableArray *B = [A mutableCopy]; 

B的内容是NSDictionary对象而不是NSMutableDictionary,对吗?

Assume

NSArray *A = xxx; // A with three NSDictionary objects
NSMutableArray *B = [A mutableCopy]; 

B's content is NSDictionary object not NSMutableDictionary, is it right?

灰色世界里的红玫瑰 2024-08-23 09:21:40
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

您必须知道这些复制内容的返回类型,并且在声明将分配给哪个新对象时,返回值必须是不可变或可变的,否则编译器将显示错误。

已复制的对象无法使用新对象进行修改,它们现在完全是两个不同的对象。

-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

You have to know the return type of these copying stuff and while declaring the new object which one will be assigned the return value must be of immutable or mutable one, otherwise compiler will show you error.

The object which has been copied can not be modified using the new one,they are totally two different objects now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文