2

有时我必须在某些条件下“加载”一个数组。所以我有一个for循环并将对象添加到一个临时的NSMutableArray。

但是,当我的组装过程完成并且我只需要一个属性中的静态数组时,最好的办法是什么?

  • 我应该为 NSArray 属性设置我的临时值吗?
  • 我应该使用 NSMutableArray 的复制方法并将其复制到属性中吗?
  • 我应该使用[[NSArray alloc] initWithArray:tempArray]吗?
  • 我应该使用[NSArray arrayWithArray:tempArray]并且有区别init吗?

继续的最佳方式(性能和内存)是什么?

4

3 回答 3

3

将 NSArray 属性作为属性通常是一个好主意copy。所以在大多数情况下,你会这样做self.myProperty = temporaryArray。通常最好让访问者为您处理这样的内存管理问题,以便将责任集中在一个小范围内。

于 2013-09-12T17:00:24.703 回答
2

NSMutableArray是 的子类NSArray,因此最简单的方法是将可变数组分配给(非可变)NSArray*变量。但是,由于 Objective-C 的运行时动态性,如果您的代码格式不正确,您最终可能会意外地改变这个预期为静态的数组。如果您创建数组的非可变副本,任何此类意外调用都将导致程序崩溃。

NSMutableArray-copy方法应该返回一个可变副本,所以我认为这不是你想要做的。您编写的最后两个选项在 ARC 的优化下是等效的;不同之处在于+arrayWithArray:返回一个自动释放的对象,而-initWithArray:返回一个保留的对象。

这是一个差异示例,如果您不小心调用了以下NSMutableArray方法-removeAllObjects

NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:n];
for (int i = 0; i != n; ++i) {
    // add object to tempArray
    [tempArray addObject:[NSNumber numberWithInt:n];
}

// option 1:
[self setArray:tempArray];
[[self array] removeAllObjects]; // succeeds (that's bad)

// option 2:
[self setArray:[tempArray copy]];
[[self array] removeAllObjects]; // succeeds (that's bad)

// option 3:
NSArray *immutableArray = [[NSArray alloc] initWithArray:tempArray];
[self setArray:immutableArray];
[[self array] removeAllObjects]; // fails (that's good)
// if not ARC: [immutableArray release];

// option 4:
NSArray *immutableArray = [NSArray arrayWithArray:tempArray];
[self setArray:immutableArray];
[[self array] removeAllObjects]; // fails (that's good)
于 2013-09-12T16:57:21.657 回答
0

所有这些解决方案在性能方面没有太大区别 - 但是我建议使用最后一个,因为它最干净:

[NSArray arrayWithArray:tempArray]

this 和 init 的区别在于 this 返回 autorelease 对象,而 init 返回 +1 retain count 对象(你必须释放它才能释放它)。

当你使用 [copy] 时也一样——你也需要释放这个对象。当然,如果您使用 ARC,则不必担心太多。

在性能方面并将其保留为属性 - 如果您可以重用构造的数组,则在您完成一次后将其保留在属性中,并且有机会重用结果。如果每次都必须重建它,请使用局部变量。

于 2013-09-12T16:55:59.640 回答