NSArray的mutableCopy-性能问题

时间:2019-02-07 21:50:12

标签: objective-c performance nsmutablearray nsarray

我有以下担忧。我有一段代码非常关心性能(说实话,我正在尝试使其尽可能优化)。

我有这样的东西:

NSArray *array = [someInstance getArray];
if (something) {
   NSMutableArray *marray = [array mutableCopy];
   [marray removeObject:someObject];
   [marray insertObject:someObject atIndex:0];

   array = marray;
}

目标是将someObject移动到数组的开头-非常简单。但是,重点在其他地方。方法[someInstance getArray]返回NSArray *,但在内部它也使用NSMutableArray

- (NSArray *)getArray {
    NSMutableArray *array = [NSMutableArray new];
    // do some stuff here
    return array;
}

我试图让我的所有接口都返回不可变的集合。但是在上述情况下,我正在考虑根据该规则创建一个例外,因为我非常在意这段代码的性能。因此,我可以将getArray方法更改为以下内容:

- (NSMutableArray *)getArray {
    NSMutableArray *array = [NSMutableArray new];
    // do some stuff here
    return array;
}

,然后如下更改我的超高效代码:

NSMutableArray *array = [someInstance getArray];
if (something) {
   [array removeObject:someObject];
   [array insertObject:someObject atIndex:0];
}

上述变化在绩效方面是否有意义?

1 个答案:

答案 0 :(得分:1)

NSArray支持写时复制。来自Foundation Release Notes for macOS 10.13 and iOS 11

馆藏写时复制

  

NSArray,NSDictionary和NSSet现在实现“写入时复制”(CoW),   这意味着可变实例的副本通常不会是完整的   复制但便宜得多的O(1)操作。完整副本仅完成   当其中一个对象(原始对象或副本)发生突变时   下线。

     

有关更多信息,请参见WWDC 2017 session 244 “Efficient Interactions with Frameworks”

这意味着复制阵列很便宜。不过,在原件仍在的情况下对其进行修改可能会非常昂贵。

因此,您可以这样做:

if (something) {
   NSMutableArray *marray = [array mutableCopy];
   array = nil;
   [marray removeObject:someObject];
   [marray insertObject:someObject atIndex:0];
   array = [marray copy];
}

复制导致两个对象共享后备存储。通过在更改array之前清除marray,应释放原件,只保留其中一个。然后,这些变异不需要复制,因为不再共享。

此外,按照该WWDC视频中的建议,当您有一种方法可以创建一个在设置时可变的数组,但又想返回不可变的数组时,可以并且应该返回一个副本,而不仅仅是直接指针:

- (NSArray *)getArray {
    NSMutableArray *array = [NSMutableArray new];
    // do some stuff here
    return [array copy];
}

那更安全而且仍然便宜。