Objective-C:autorelease confusion

时间:2012-01-06 16:10:30

标签: objective-c memory-management

假设我有一个类DoStuff,并且该类有两个方法,如此

- (NSMutableDictionary* returnToCaller) methodOne : (NSString* ) myString {

    NSMutableDictionary* bundleOfJoy = [[NSMutableDictionary alloc] init]; 

    if (myString) { 
       bundleOfJoy = [self methodTwo];
    }

    return bundleOfJoy; 

} 

- (NSMutableDictionary* returnToMethodOne) methodTwo {

    NSMutableDictionary* anotherDictionary = [[NSMutableDictionary alloc] init]; 
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return anotherDictionary;  
}
好吧,所以忍受我,因为我的记忆管理有点弱。我不能释放返回后手动创建的两个词典,因为不会调用release命令。在返回之前我不能这样做,或者我没有传递任何值。我的理解是处理这个问题的方法是使用自动释放池......

pool = [[NSAutoreleasePool alloc] init];

并初始化我的对象

NSMutableDictionary* anotherDictionary = [[[NSMutableDictionary alloc] init] autorelease];

然后致电

[pool drain];

所以,如果这是正确的,我在哪里初始化池?在awakeFromNib中?我在哪里打[池排水]?

如果这是不正确的,有人会把我拉直(但请慢慢打字):D

感谢

6 个答案:

答案 0 :(得分:2)

每个帖子中都有一个自动NSAutoreleasePool,你不必创建一个而不是创建一个新线程。

使用[pool release];而不是[池排水],除非有内存泄漏。

对于您的代码,该方法负责释放已分配的对象,因此添加

 return [bundleOfJoy autorelease]; 
 return [anotherDictionary autorelease];

答案 1 :(得分:2)

系统会为您维护一个自动释放池。它是在程序启动之前创建的,并在事件循环获得控制时定期耗尽。在大多数情况下,您不需要自己的自动释放池:只需在返回对象之前调用autorelease,您就可以了。

P.S。如果您想了解需要自己的自动释放池的情况,Apple put together a nice guide为您服务。

答案 2 :(得分:2)

在大多数情况下,已经为您设置了自动释放池。除非您在不使用GCD的情况下在单独的线程中运行代码,否则不需要分配和排空池。即使您确实在该方法中放置了自动释放池,对象也会过早自动释放,因为您必须在同一方法中排空。据说要获得一个自动释放的对象,您可以使用便利构造函数或将autorelease添加到alloc/init

- (NSMutableDictionary* /*returnToMethodOne*/) methodTwo {
    //Convenience constructor
    NSMutableDictionary* anotherDictionary = [NSMutableDictionary dictionary];
    //or    
    //NSMutableDictionary* anotherDictionary = [[[NSMutableDictionary alloc] init] autorelease]; 
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return anotherDictionary; 
}

答案 3 :(得分:2)

你通常不会自己创建和排空池,它是由你的框架完成的,所以你只需要自动释放你想要在以后发布的对象。

当然这种方式你无法控制时间,所以万一你在程序的某些部分创建了很多临时自动释放的对象,你可以将这段代码包装在pool create和drain中:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
... create objects...
[pool drain];

但正如我所说,这只是特殊情况的选择。

答案 4 :(得分:2)

最好的解决方案是使用ARC。那你再也不用担心了。 :)

即便如此,您还需要了解ARC正在为您做些什么。我的iOS编程书中的讨论同样适用于Mac OS X:

http://www.apeth.com/iOSBook/ch12.html#_memory_management

答案 5 :(得分:1)

您需要autorelease您返回的对象。它们将存在供您的调用代码使用,但将在稍后的某个任意点释放。

- (NSMutableDictionary* returnToMethodOne) methodTwo {
    NSMutableDictionary* anotherDictionary = [[NSMutableDictionary alloc] init]; 
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return [anotherDictionary autorelease]; 
}

除非您在运行生成大量对象的循环时需要确保内存使用率较低,否则几乎不需要使用自动释放池。

实现此功能的另一种方法是创建一个自动释放的对象,您不必管理内存(使用便利构造函数)。例如:

- (NSMutableDictionary* returnToMethodOne) methodTwo {
    NSMutableDictionary* anotherDictionary = [NSMutableDictionary dictionary]; // Creates an autoreleased NSMutableDictionary object.
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return anotherDictionary; // No `autorelease` call because it's not our memory to manage.
}