- (NSArray *)map:(id (^)(id))block {
NSEnumerator * enumerator = self.objectEnumerator;
NSMutableArray * array = [NSMutableArray array];
id obj;
while ((obj = enumerator.nextObject)) {
[array addObject:(block(obj) ?: [NSNull null])];
}
return array (NSMutableArray *); or return array.copy (NSArray *)
}
这是 NSArray
上的类别答案 0 :(得分:4)
使用返回类型,而不是自省
要确定它是否可以更改接收的对象,消息的接收者必须依赖于返回值的正式类型。例如,如果它接收到一个类型为immutable的数组对象,它就不应该尝试改变它。根据类成员资格确定对象是否可变是不可接受的编程习惯。
[...]
您不应该基于类成员资格来假设对象是否可变。您的决定应该完全取决于出售该对象的方法的签名对其可变性的描述。如果您不确定对象是可变的还是不可变的,则假设它是不可变的。
一般来说:
如果您的来电者遵循这些指导原则,只需返回可变数组,因为它稍微便宜一点,并且来电者不会改变它。
如果您不确定来电者是否可能不遵守这些指南,并且您想要采取防御性措施,请使用array.copy
返回不可变副本。
具体到这种情况,它并不重要,因为即使调用者改变它,你也不会再次使用该数组实例。
答案 1 :(得分:3)
在给定的代码中,创建可变数组只是为了返回。它不是由其他任何东西持续进行的。因此,直接归还是没有危险的。
返回一个可变数组有两个主要危险,它继续由返回代码保存:
因此,如果该方法返回一个可变数组,它继续保持对引用的引用,那么它应该返回一个副本。
答案 2 :(得分:3)
在这种情况下,您不需要复制。
数组对象是在本地创建的,因此无法通过其他方式对其进行意外修改。
接口只指定它返回NSArray *
,因此只要它返回一种NSArray *
,它就满足了要求。它是返回MyCustomArray *
还是NSMutableArray *
纯粹是实现细节,它在调用者点视图中不会产生任何影响。
但是,如果共享数组对象,则执行需要返回它的副本。否则NSArray
上的不可变假设可能会被破坏并导致意外行为。
答案 3 :(得分:0)
这取决于您返回的方法类型。如果你的返回类型是不可变的,请使用copy或者mutableCopy。
答案 4 :(得分:0)
在大多数情况下,无需创建副本,因为您没有在方法之外另外引用array
。
__NSArrayM
而另一个__NSArrayI
。
编译器会通过不让您直接在返回的NSArray
上调用突变消息来保护您,但这并不能阻止您简单地将__NSArrayM
转换为NSMutableArray
或执行对象上的突变选择器并绕过编译器。在__NSArrayI
上调用突发消息会导致应用程序崩溃,因此如果您想要保证此安全性,请在返回时调用copy
即可。