我是内存托管代码的新手,但我很清楚这个想法。
在我的应用程序通过XCode中的泄漏工具,我注意到我只需要清理我的自定义对象,但不是动态创建的数组,所以我认为这些数据类型是自动释放的 - 这是有意义的,因为我只需要释放我用作具有(保留)它们的属性的数组。
然后我注意到一些奇怪的事情:我在某个初始化的数组上发生泄漏:
NSMutableArray *removals = [NSMutableArray new];
但不是类似的
NSMutableArray *removals = [NSMutableArray arrayWithCapacity:9];
现在,设置“new”的原因是它可能有0-99个项目,而另一个我知道它将始终是9.因为两个数组后来都传递给相同的方法基于用户交互,如果我没有在方法结束时发布,或者如果我没有发布,我要么是泄漏了!
我将第一个数组更改为
NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99];
我没有泄漏,也没有发布任何东西。谁能解释一下?
答案 0 :(得分:65)
正如memory management rules中所述,只要您拥有使用+alloc
,+new
,-copy
或-mutableCopy
创建的对象,它并负责在某个时候发布它。 (事实上,+new
只是[[MyClass alloc] init]
的简写。)正如您所说,通过[NSArray new]
创建数组而不释放它是一个内存泄漏。但是,如果正确处理此对象,通常可以在某个时刻释放它。例如:
如果使用的方法是从 中创建数组的方法调用的,那么您应该能够在数组之后释放该数组被使用过。如果内部方法需要对数组保持更永久的引用,那么该方法负责将-retain
和最终-release
发送到对象。例如:
- (void)myMethod {
NSArray *removals = [NSArray new];
// ...
[someObject someOtherMethod:removals];
[removals release];
}
如果您使用 -init
方法为对象创建了数组,那么 -dealloc
方法可以在对象被破坏。
如果你需要创建数组,然后从方法中返回,你就会发现自动释放的发明原因。您的方法的调用者不负责释放对象,因为它不是+alloc
,+new
,-copy
或-mutableCopy
方法,但您需要确保它最终被释放。在这种情况下,您在返回对象之前手动调用-autorelease
。例如:
- (NSArray *)myMethod {
NSArray *removals = [NSArray new];
// ...
return [removals autorelease];
}
当您通过+arrayWithCapacity:
创建数组时,您没有调用其中一种“特殊”方法,因此您不必释放结果。这可能与-autorelease
一起实现,与上面的上一个示例非常相似,但不一定如此。 (顺便提一下,你也可以使用[NSMutableArray array]
创建一个空的自动释放的NSMutableArray;该方法可以在NSArray中找到,因此它不会出现在NSMutableArray下的文档中,但它会在发送到NSMutableArray时创建一个可变数组如果你要从你的方法返回数组,你可以使用它作为[[[NSMutableArray alloc] init] autorelease]
的简写 - 但它只是一个捷径。但是,在许多情况下,您可以使用-init
或+new
创建对象,并在适当的时候手动释放它。
答案 1 :(得分:7)
这是在幕后实现的方式:
+(NSMutableArray*) new
{
return [[NSMutableArray alloc] init];
}
和
+(NSMutableArray*) arrayWithCapacity:(NSNumber)capacity
{
return [[NSMutableArray alloc] initWithCapacity:capacity] **autorelease**];
}
在第一种情况下,数组仅被分配,您负责取消分配它。相反,arrayWithCapacity已为您自动释放,即使您忘记取消分配也不会导致泄漏。
答案 2 :(得分:4)
Cocoa使用某些命名约定。任何以alloc,new或copy开头的东西都会返回一个retainCount为1的东西,并且你需要释放它。函数返回的任何其他函数都有一个平衡的retainCount(它可能由其他东西持有,或者它可能会被保留并释放出来)。
所以:
NSMutableArray *removals = [NSMutableArray new];
keepCount为1,并且:
NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99];
或
NSMutableArray *removals = [NSMutableArray array];
不要因为这些方法没有使用alloc,new或copy作为前缀。这一切都在内存管理documentation中详细说明。特别是:
如果您拥有对象的所有权 使用名称为的方法创建它 以“alloc”或“new”开头 包含“复制”(例如,alloc, newObject,或mutableCopy),或者如果你 发送一条保留信息。你是 负责放弃 您拥有的对象的所有权 释放或自动释放。任何其他时间 你收到一个物品,你绝对不能 释放它。