您对Objective-C中的申报类型有多谨慎?

您对Objective-C中的申报类型有多谨慎?,objective-c,cocoa,coding-style,Objective C,Cocoa,Coding Style,假设您有一个方法返回一个新生成的NSArray实例,该实例是使用NSMutableArray在内部构建的。你总是这样做吗: - (NSArray *)someArray { NSMutableArray *mutableArray = [[NSMutableArray new] autorelease]; // do stuff... return [NSArray arrayWithArray:mutableArray]; // .. or [[mutableArra

假设您有一个方法返回一个新生成的NSArray实例,该实例是使用NSMutableArray在内部构建的。你总是这样做吗:

- (NSArray *)someArray {
    NSMutableArray *mutableArray = [[NSMutableArray new] autorelease];
    // do stuff...
    return [NSArray arrayWithArray:mutableArray];  // .. or [[mutableArray copy] autorelease]
}
或者,由于NSMutableArray是NSArray的一个子类,您是否只保留可变数组对象的原样并直接返回它:

- (NSArray *)someArray {
    NSMutableArray *mutableArray = [[NSMutableArray new] autorelease];
    // do stuff...
    return mutableArray;
}

就我个人而言,当我从这样的方法返回时,我经常将可变数组转换为NSArray,只是因为我觉得它更“安全”或更“正确”。尽管说实话,我从来没有遇到过将可变数组转换为NSArray的问题,所以这在现实中可能不是一个问题-但是对于这种情况有没有最佳实践?

将NSMutableArray转换为NSArray是很常见的。我想大多数程序员都会意识到,如果他们对一个不可变的对象进行降级并对其进行变异,那么他们就会引入讨厌的bug


另外,如果您有一个NSMutableArray ivar
someMutableArray
,并且在KVC访问器方法中返回
[NSArray arrayWithArray:someMutableArray]
,它可能会搞乱KVO。您将开始收到“对象已解除分配,观察者仍处于连接状态”错误。

NSArray实际上是一个类群集,而不是一种类型。因此,无论你在哪里看到NSArray,它都可能已经是几种不同类型中的一种了。因此,“转换为NSArray”有些误导;NSMutableArray已经符合NSArray接口,这是大多数人将要处理的问题

在任何情况下,如果您正在返回一个数组(并且由于autorelease,之后没有保留它),您可能不需要担心数组是否是可变的


但是,如果您保留数组,那么您可能希望这样做,以防止客户端更改内容。

我曾经执行
返回[NSArray arrayWithArray:someMutableArray]
,但我慢慢地确信它没有任何实际好处。如果API的调用方将返回的对象视为声明类的子类,那么他们就错了


[注意:请参阅下面bbum的警告。]

没有NSArray协议。NSMutableArray是NSArray类的一个子类。Peter,你完全正确,这是我的一个错误——这里的“接口”是指“接口”。我已经相应地更新了我的答案。我大体上同意。然而,如果调用代码处理返回值的可能性会导致严重问题,那么防御性复制是一个好主意。对于框架代码来说尤其如此。如果调用代码正在改变API所说的应该被视为不可变的东西,那么它们应该执行
-mutableCopy
。否则,就做错了(如果你觉得必须这样做,没有什么能阻止你采取防御措施。)但是,真正的问题是,如果你返回一个可变数组引用到一个数组,该数组可能会在以后发生变异,那么接收NSArray*的调用方可能会认为内容永远不会改变。。。而且。。。好。。。轰,这是真的。实际上,我可能只在方法本身中创建可变数组时才返回该数组(比如说,不是实例变量)。(我之所以说“可能”,是因为我无法备份它,尽管我一定要检查我愚蠢地没有这样做的情况。)