在没有自动释放的情况下,如何在iPhone上释放在实例方法中创建的对象?

在没有自动释放的情况下,如何在iPhone上释放在实例方法中创建的对象?,iphone,objective-c,cocoa-touch,memory-management,Iphone,Objective C,Cocoa Touch,Memory Management,我对iPhone开发相当陌生,在对内存管理的理解上遇到了障碍。我通读了这本书,读了许许多多的问题和答案,但还没有找到一个完整的答案 如果我有一个创建对象的实例方法,那么我看到的每个示例似乎都使用自动释放调用: -(NSArray *)findThings { NSArray* things = [[[NSArray alloc] init] autorelease]; // add some lovely things to my shiny new array retu

我对iPhone开发相当陌生,在对内存管理的理解上遇到了障碍。我通读了这本书,读了许许多多的问题和答案,但还没有找到一个完整的答案

如果我有一个创建对象的实例方法,那么我看到的每个示例似乎都使用自动释放调用:

-(NSArray *)findThings {
    NSArray* things = [[[NSArray alloc] init] autorelease];
    // add some lovely things to my shiny new array
    return things;
}
忘记了这个人为的例子,我读到的关于iphonedev最佳实践的所有内容都说不鼓励使用自动释放池,但是如果没有自动释放池,我如何实现上面的例子呢?如果这个方法被多次调用,我会觉得我冒着用“东西”堵塞iPhone自动释放池的风险,这似乎与在这样一个受限的平台上将资源使用保持在最低限度的需求背道而驰

我认为:

-(NSArray *)findThings {
    NSArray* things = [[NSArray alloc] init];
    // add some lovely things to my shiny new array
    [things release];
    return things;
}
但是,在传递给调用方法之前,“things”的retain计数将为零,因此我觉得在调用[things release]和调用findThings的方法实际使用结果之间释放对象的风险很大

我被《内存管理指南》中的规则弄糊涂了,该规则规定:

接收到的对象通常是 保证在有效期内保持有效 方法采用随机对照法。(……)这种方法 也可以安全地将对象返回到 它的调用者

我不确定这是否意味着作为实例方法的编写者,在调用方法的作用域结束之前,我可以安全地执行发布,而不会有对象被释放的风险,或者,作为apple提供的框架中类的用户,我可以假设,只要该方法的名称中没有new/init/alloc/copy/whatever,我就不必担心从这些类接收到的对象的retain/release/etc

总而言之

  • 我可以在返回对象之前使用release而不是autorelease来避免在iPhone上使用autorelease池吗
  • 如果没有,是否有更好的模式不涉及自动释放池
  • 我是不是错过了一些基本的东西?文件上好像有个洞

提前感谢

好的自动释放可以覆盖您遇到问题的确切场景。

您可以遵循以下步骤

忘记了这个人为的例子,我读到的所有关于iPhone开发最佳实践的文章都说不鼓励使用自动释放池


不鼓励使用自动释放池;它们在Cocoa中随处可见,正确使用时对内存使用没有任何影响。只有当自动释放池被人为地延长了大量对象的寿命(例如在循环中)时,才需要考虑自动释放池。在这种情况下,您可以手动管理自动释放池。

省去您的麻烦。。只要做:

- (NSArray *)findThings{
      NSArray *things = [NSArray array];
      return things;
}
正如stefanB之前提到的,autorelease是用来解决您在这里遇到的问题的。
另一个解决方案可能是保留它,然后在使用它的地方发布。。但是,如果您不小心,这可能会导致泄漏。

正如其他人所说的,自动释放就是为这个问题而设计的

当从实例方法创建和返回对象时,对象在返回之前应该自动释放

这迫使调用程序遵循正确的内存管理规则,而无需付出额外的努力来确保这一事实


当发送方从一个不包含单词Create、Alloc、Retain或New的方法返回一个对象时,结果将按约定自动释放。这让程序员很容易知道,如果他们想保留对象,就应该保留它,或者在当前范围内可以安全地使用和忘记它,而不必担心它的内存。

是的,在iPhone开发中不鼓励使用自动释放池,因为它们不是绝对必要的。他们不鼓励这样做,因为这样可以让对象在内存中停留的时间比需要的时间更长。在内存不足的iPhone上开发应用程序时,这是一个问题。自动释放的对象在返回到main.c中创建的主自动释放池之前不会被释放,这可能需要很长时间(除非您创建了自己的自动释放池,否则我将在最后讨论此问题。)

不需要自动释放对象的情况:

NSString *string = [NSString stringWithString:@"hello world"];
//use string
第一种情况更方便,因为我不必担心以后释放字符串,但它可以很容易地替换为:

NSString *string = [[NSString alloc] initWithString:@"hello world"];
// use string
[string release];
对于这些情况,建议避免自动释放对象


当您使用autorelease传回对象时,不可避免

您必须使用:

-(NSArray *)findThings {
    NSArray* things = [[[NSArray alloc] init] autorelease];
    // add some lovely things to my shiny new array
    return things;
}
因为只要调用
release
,对象就无效

-(NSArray *)findThings {
    NSArray* things = [[NSArray alloc] init];
    // add some lovely things to my shiny new array
    [things release];
    // things is now in invalid object if you could potentially use things later it should be set to nil to avoid a crash
    things = nil; // sending messages to nil is okay, it won't cause a crash, sending messages to a released object is not okay, it can cause unpredictable crashes.        
    return things;
}

在使用大量自动释放内存的情况下,您应该创建并耗尽自己的自动释放池,以便自动释放内存不会停留在必要的时间

-(void)useLotsOfAutoReleasedObjects {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    // lots of autoreleased object
    // large autoreleased objects
    [pool drain];  // autorelease objects are released too
}

[pool drain]也会释放内存池,有关更多信息,请参阅。

是的,但这实际上根本没有解决我问题的实质。在手动内存管理领域,它可以节省您的时间!根据这个()的说法,它们是,但也许我只是把它看得太字面了:“iPhone操作系统注意:因为在iPhone操作系统上,应用程序在内存更为有限的环境中执行,所以在方法或代码块(例如,循环)中不鼓励使用自动释放池应用程序创建多个对象的地方。相反,只要可能,您应该显式释放对象。”关键短语是“应用程序创建多个对象的循环”。在循环中,您希望手动释放临时对象,或者管理自己的自动释放池。问题中使用的示例可能仅使用数组来说明手头的问题。J