在声明2D阵列时警告“在线分配的对象的潜在泄漏...”

时间:2011-04-12 09:20:50

标签: objective-c

最初我以这种方式宣布了一个2D数组:

subUrb = [[NSArray alloc] initWithObjects:
     [[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"East",@"South", @"West", @"North", nil] ,
     [[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Kuala Lumpur SubUrb1", @"Kuala Lumpur SubUrb2", nil],
     [[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Jakarta SubUrb1",nil],
     nil]; 

但是当我试图“分析”项目的警告时,我在这段代码中遇到了三种相同类型的问题 - “在xxx线上分配的对象的潜在泄漏”

我注意到要摆脱它,我必须这样写:

subUrb = 
    [[NSArray alloc] initWithObjects:
        [[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"East",@"South", @"West", @"North", nil] autorelease],
        [[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Kuala Lumpur SubUrb1", @"Kuala Lumpur SubUrb2", nil] autorelease],
        [[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Jakarta SubUrb1",nil] autorelease],
        nil];

然后我不会得到任何分析警告。但我不喜欢这样......这不符合逻辑。实际上,我的控制器中永远不会释放这个2D数组,整个2D数组应该在PickerView的控制器的整个生命周期内保留。

我应该如何更优雅地声明2D阵列?

6 个答案:

答案 0 :(得分:2)

1:NARC

如果你发送+alloc,你拥有该对象,你有责任释放它。因此

[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"East",@"South", @"West", @"North", nil]

创建一个由你拥有的数组,因此你应该释放它。

2:Cocoa集合拥有自己的元素

当您将对象添加到Cocoa集合(例如NSArray)时,该集合拥有该对象。当它们不再使用时,它还会释放集合中的所有元素。

3:结论

没有-autorelease的代码会为最外层数组和最外层数组元素的每个内部数组提供的所有权。这意味着您负责释放这四个阵列(一个最外面,三个最里面)。但是,由于最外层的数组已经拥有最内层的数组,因此您可能也不需要拥有它们,因此-autorelease

答案 1 :(得分:1)

你的第二种方法是正确的。关键是封闭数组将取得嵌套对象的所有权,而通过alloc获得的额外所有权留置权则悬空。一种略微更简洁的方法是使用类方法arrayWithObjects而不是alloc / initWithObjects / autorelease,但这相当于一样。

答案 2 :(得分:1)

如果您使用alloc init分配数组,则获得所有权,因此您必须像在第二个代码中那样释放它。 您还可以使用:  [[NSArray alloc] initWithObjects: [NSArray arayWithObjects:first,second, nil], nil];

答案 3 :(得分:0)

即使在控制器的整个生命周期中都需要数组,你应该在控制器的dealloc方法上释放它,否则对象会泄漏。

答案 4 :(得分:0)

如果它从未被释放,那么两种方式都不会泄漏,但第二种方式更“正确”。在父数组(从不)之前,NSArrays不会被自动释放,所以它很好。

答案 5 :(得分:0)

将子数组添加到父数组时,父数组会保留子数组。因此,将保留计数增加到2.由于您没有在其他任何地方保留对子数组的引用,因此保留计数应该只为1,因此您应该使用自动释放。所以你的第二个版本是正确的。