-copy什么时候返回一个可变对象?

rub*_*gly 9 cocoa objective-c mutable nsmutableurlrequest

我读了Cocoa和Objective C:Up and Running,-copy它将始终返回一个不可变对象并-mutableCopy始终返回一个可变对象:

重要的是要知道调用-copy一个可变对象会返回一个不可变的版本.如果要复制可变对象并在新版本中保持可变性,则必须调用-mutableCopy原始对象.但这很有用,因为如果你想"冻结"一个可变对象,你可以调用-copy它.

所以我有这样的事情:

NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
NSLog( @"%@", [req className] );               // NSMutableURLRequest
NSLog( @"%@", [[req copy] className] );        // NSMutableURLRequest
NSLog( @"%@", [[req mutableCopy] className] ); // NSMutableURLRequest
Run Code Online (Sandbox Code Playgroud)

根据之前的回答:

你不能依赖复制的结果是可变的!复制一个NSMutableArray可以返回一个NSMutableArray,因为那是原始类,但复制任意 NSArray实例都不会.

这似乎有点孤立NSURLRequest,因为NSArray按预期行事:

NSArray *arr = [[NSMutableArray alloc] init];
NSLog( @"%@", [arr className] );                 // __NSArrayM
NSLog( @"%@", [[arr copy] className] );          // __NSAraryI
NSLog( @"%@", [[array mutableCopy] className] ); // __NSArrayM
Run Code Online (Sandbox Code Playgroud)

所以...

  1. 什么时候-copy返回一个不可变对象(如预期的那样)以及何时返回一个可变对象?
  2. 如何获得拒绝被"冻结"的可变对象的"冻结"副本的预期效果?

jtb*_*des 13

我想你已经发现了文档和现实之间的巨大分歧.

NSCopying协议文档声称:

如果考虑"immutable vs. mutable"适用于接收对象,则返回的副本是不可变的; 否则,副本的确切性质由班级决定.

但在某些情况下,这显然是错误的,正如您在示例中所示(我已经通过该文档页面向他们发送了反馈).

但是(#2)在我看来,它实际上并不重要,你不应该在乎.

关键-copy在于它将返回一个可以使用的对象,并保证它将独立于原始对象.这意味着如果您有一个可变对象,-copy并且更改原始对象,则副本将看不到该效果.(在某些情况下,我认为这意味着-copy可以优化不做任何事情,因为如果对象是不可变的,它首先不能改变.我可能是错的.(我现在想知道它的含义是什么因为这个是字典键,但这是一个单独的主题......))

正如您所见,在某些情况下,新对象实际上可能是一个可变类(即使文档告诉我们它不会).但只要你不依赖它是可变的(为什么你呢?),这没关系.

你该怎么办?始终将结果-copy视为不可变,简单.