这是使用NSAutoreleasePool的正确方法吗?

时间:2012-05-01 15:50:36

标签: objective-c ios memory-management autorelease

我是Objective-C的新手,我不确定我是否正确使用NSAutoreleasePool。

  1. 如果我只想使用一次自动释放:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool release]; //newText will be released
    
  2. 如果我想多次使用autorelease,我会使用:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool drain]; //newText will be released
    newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool drain]; //newText will be released
    newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool release]; //newText will be released
    
  3. 这样好吗?有没有内存泄漏?

4 个答案:

答案 0 :(得分:3)

我想说调用[pool drain]是不必要的。我从来没有见过它们在实践中使用过。我想如果你在自动释放池中分配大量内存,可能是必要的。但在典型的情况下,我认为不会。

顺便说一句,您将希望开始使用以下构造用于自动释放池:

@autoreleasepool {
    ... your code ...
}

这显然比“旧”方式(你的方式)更有效率。在功能上,它是相同的,但在内部它表现得更好。最近的Xcode / iOS发行说明中有一些相关内容。

答案 1 :(得分:3)

很抱歉这样说,但RTFM。在调用-drain之后,池将自行释放,因此它无效。

目前,在使用Apple的LLVM编译器的objective-c中,有一个名为@autoreleasepool的语言添加,可以同时使用ARC和非ARC代码,您可以这样使用:

@autoreleasepool {
    // code that will automatically have any -autoreleased variables cleaned up.
} 

答案 2 :(得分:3)

(2)不行。 -drain-release是等效的(在引用计数环境中),并且在-drain后自动释放池被释放。因此,您将双重释放自动释放池对象并使程序崩溃。

即使在ARC之前,除非你在非常严格的内存预算中工作,否则在样板main()之外创建一个NSAutoreleasePool是不典型的。无论如何,进入池中的对象-autorelease将在NSRunLoop的每个滴答之后释放。如果严格遵守所有权转移规则,则不会发生内存泄漏(请参阅Understanding reference counting with Cocoa and Objective-C)。

启用了 ARC,您甚至不需要关心这一点 - 编译器会在适当的位置插入-retain-release。< / p>


此外,如果sliderLabel.text被标记为@property(retain)(或(strong)),则释放(1)中的自动释放池将不会释放newText,因为该对象现在拥有新的所有者

答案 3 :(得分:3)

通常情况下,如果您在主线程上并且没有使用大量资源密集型代码,则无需创建自己的自动释放池。只需使用为您创建的默认值。

如果你是多线程的,或者你正在做一个内存密集的长时间循环(你可能不应该在主线程上做),你只需要创建自己的循环。