Objective C版本,自动释放和数据类型

时间:2009-08-02 19:11:41

标签: iphone objective-c xcode release retain

我是内存托管代码的新手,但我很清楚这个想法。

在我的应用程序通过XCode中的泄漏工具,我注意到我只需要清理我的自定义对象,但不是动态创建的数组,所以我认为这些数据类型是自动释放的 - 这是有意义的,因为我只需要释放我用作具有(保留)它们的属性的数组。

然后我注意到一些奇怪的事情:我在某个初始化的数组上发生泄漏:

NSMutableArray *removals = [NSMutableArray new];

但不是类似的

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:9];

现在,设置“new”的原因是它可能有0-99个项目,而另一个我知道它将始终是9.因为两个数组后来都传递给相同的方法基于用户交互,如果我没有在方法结束时发布,或者如果我没有发布,我要么是泄漏了!

我将第一个数组更改为

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99];

我没有泄漏,也没有发布任何东西。谁能解释一下?

3 个答案:

答案 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),或者如果你   发送一条保留信息。你是   负责放弃   您拥有的对象的所有权   释放或自动释放。任何其他时间   你收到一个物品,你绝对不能   释放它。