NSMutableArray属性 - 释放子项

时间:2011-10-09 17:51:22

标签: iphone objective-c ios

以下是我在运行以下代码时看到的内容:

// Dealloc on MyClass not called
MyClass* c = [MyClass new];
self.a = [NSMutableArray new];
[self.a addObject:c];
[c release];
[a release];

// Dealloc on MyClass called
MyClass* c2 = [MyClass new];
NSMutableArray* a2 = [NSMutableArray new];
[a2 addObject:c2];
[c2 release];
[a2 release];

// Dealloc on MyClass called
MyClass* c3 = [MyClass new];
a = [NSMutableArray new];
[a addObject:c3];
[c3 release];
[a release];

为什么在第一个例子中没有调用dealloc?

编辑:

我想我误解了这一切。基本上我需要做的是:

NSMutableArray* alocal = [NSMutableArray new]; // alocal has a retain count of 1
self.a = alocal; // a has a retain count of 1
[alocal release]; // alocal has a retain count of 0
[a release]; // a has a retain count of 0

OR

self.a = [[NSMutableArray new] autorelease]; // a has a retain count of 2
[a release]; // a has a retain count of 0

OR

self.a = [NSMutableArray array]; // a has a retain count of 2
[a release]; // a has a retain count of 0

就像注释一样,使用自动释放/数组选项(#2和#3),a不会立即释放,所以如果你想要更多的控制,请选择#1。

谢谢!

2 个答案:

答案 0 :(得分:3)

因为在第一个示例中,假设a是保留/复制属性,则数组会泄漏。

self.a = [NSMutableArray new];
顺便说一句,它与第三个例子不同:

a = [NSMutableArray new];

在第三种情况下,对象直接分配给ivar(不涉及属性设置器)。

回到第一个例子,方法new返回一个保留对象(+1),然后属性setter也保留对象(+2)。然后,当释放属性(-1)时,最终得到+1。这是错的。您需要平衡您的保留/发布以最终得+0。

一个简单的解决方案是使用便利构造函数

self.a = [NSMutableArray array];

在这种情况下,方法array返回一个自动释放的对象(+0),属性setter保留对象(+1),它由属性的释放(-1)平衡,你结束用+0。


此外,在第一个示例中,您通过ivar:

释放您设置为属性的对象
[a release];

结果,该属性现在持有一个指向可能已释放的对象的指针。由于您放弃了对象的所有权,因此无法保证该对象将来会存活。如果该对象实际上已被释放(因为它没有任何其他所有者),您的指针仍将指向该对象过去所在的堆中的内存地址;除了现在,该地址可能包含任何内容:所述对象的旧位模式,或不相关的对象,或绝对垃圾。

如果您向解除分配的对象发送消息,例如,没有任何好处,例如它会让你的应用程序崩溃。要避免这种情况,请通过属性释放对象:

self.a = nil;

答案 1 :(得分:0)

这取决于你如何实施属性'a' 它应该是:

@property (retain) NSMutableArray *a;

当使用'new'时,它正在进行分配,所以你应该像这样自动释放它:

self.a = [[NSMutableArray new] autorelease];