释放可可的iPhone

问题描述:

/自动释放混乱,我慢慢地自学可可为iPhone(通过Stanford Class on iTunes U)和我刚刚通过对内存管理的部分走了,我想希望得到一些证实的假设我正在处理如何处理内存以及[释放]和[autorelease]如何工作。由于内存管理是一个非常基础且基本的,但非常重要的编程经验的一部分,我想确保我做对了。释放可可的iPhone

据我所知,有什么页头,新,或复制需要被释放。
如果我这样做:

NSString *temp = [[NSString alloc] initWithString:@"Hello World"]; 

然后我需要添加[临时发布/自动释放]最后,因为我有一个页头。

但是,如果我这样做:

NSString *temp = @"Hello World"; 

然后,它似乎并不需要释放的语句。 NSString类是否作为赋值的一部分自动调用autorelease?

此外,有没有这些语句后,这里两个*临时对象之间有什么区别?它们都包含相同的字符串,但它们在哪里有不同的内存/使用方式?

其次,性能,我假设自动释放自动处理。如果我有这样的:

@interface Person : NSObject 
{ 
    //ivars 
    NSString *firstName; 
    NSString *lastName; 
} 

//properties 
@property NSString *firstName; 
@property NSString *lastName; 

///next file 

@implementation Person 

@synthesize firstName; 
@synthesize lastName; 

- (void) dealloc 
{ 

    //HERE!!!! 

    [super dealloc]; 
} 

我假设我并不需要添加[名字发布]和[姓氏释放(在//此处!!!!),因为这是自动的处理性能。那是对的吗?

我也明白,如果我这样做的代码(假设我定义initWithFirstName):

Person *Me = [[Person alloc] initWithFirstName: @"Drew", lastName:"McGhie"]; 

,后来我将不得不使用[我发布/自动释放]。

任何确认或修正我的理解迄今帮助是极大的赞赏。

邮政的答案写了

我以为会在所有的答案,测试出的建议后,我会写这一切并谈什么工作。

我需要添加[名字发布],[姓氏发行],但我还需要(保留)添加到属性的描述。不添加(保留)导致的警告,因为它假定(分配)。下面是我终于成立了类

@interface Person : NSObject 
    { 
     //ivars 
     NSString *firstName; 
     NSString *lastName; 
    } 

    //properties 
    @property (retain) NSString *firstName; 
    @property (retain) NSString *lastName; 

    ///next file 

    @implementation Person 

    @synthesize firstName; 
    @synthesize lastName; 

    - (void) dealloc 
    { 
     [firstName release]; 
     [lastName release]; 
     [super dealloc]; 
    } 

规则很简单:如果你有alloccopyretain,这是你的责任release。如果你没有,那不是。但是,如果您需要依赖留在的物体,则必须retain(和随后的release)。

我们可以根据规则处理字符串文字 - 您不需要release它,因为您不拥有它。这很简单;没有必要担心他们是否是特殊情况,只要遵守规则,你就会好起来的。

我写了一篇博文,收集了articles about the Cocoa memory management rules;我建议跟进一些参考。

最后部分第一条:您确实将有自动/释放Me。但是,您还必须在-dealloc中添加[firstName release];[lastName release];;或更好; self.firstName = nil;

至于字符串文字;这部分有点毛,但[@"String literal" release]实质上是一个noop。因此,这两个临时对象之间的区别,但是因为您通常不会知道要处理哪个对象,所以添加了[temp release];通常是安全的选择,除非你知道它会包含一个自动释放的对象。

+0

我没有明确地分配/复​​制/保留firstName或lastName。这是否需要,因为alloc是通过综合自动生成来推断的,我只是在代码中看不到? – 2009-07-13 19:12:56

+0

从某种意义上说。问题的关键在于你的对象拥有firstName和lastName,所以当它们被设置时,它就成为你释放它们的责任。 – 2009-07-13 19:29:02

  1. 我从来没有发布像NSString *foo = @"x";字符串常量。从逻辑上讲,如果你不得不release的结果,你将不得不release参数initWithString,并且这两个参数也要initWithFirstName:lastName:
  2. 您必须做releaseautoreleasefirstNamelastName。我已经看到了有关在析构函数中不使用属性语法的警告,我认为这与在C++构造函数和析构函数中不使用虚函数的原因相同。

你的假设是错误的。你必须这样做要么这一点:

Person *Me = [[Person alloc] initWithFirstName: @"Drew" 
              lastName: @"McGhie"]; 
    ... 
    [Me release]; 

或本:

Person *Me = [Person personWithFirstName: @"Drew" 
            lastName: @"McGhie"]; 

...,并确保您的Person对象处理+personWithFirstName:lastName:正确,即[[[self alloc] initWithFirstName: firstName lastName: lastName] autorelease]

你应该做一个代码较少的人。清晰度很重要,NSAutoreleasePool可能永远不会成为你的瓶颈,如果它永远是它很容易修复。

我认为人们付出了很多努力,以避免返回autorelease'd对象,这是不合适的类消息。这是过早的优化,因为它可能不是必要的,甚至可能不是正确的做法。而且难以维持,你很可能会永远追逐泄漏。

而且,你要autorelease一个对象,你必须init(即alloc + initPersonWithFirstName:lastName:,而不是使用像personWithFirstName:lastName:一类的消息),我建议你马上去做。否则,你可能会追逐同样的泄漏。所以,如果你不打算到personWithFirstName:lastName:方法添加到Person,而是执行此操作:

Person *Me = [[[Person alloc] initWithFirstName: @"Drew" 
              lastName: @"McGhie"] autorelease]; 

摘要:可可做了很多帮助您与内存管理。确保你不打架。

根据Jon在评论中的反馈进行了更新。

+0

而不是[[[个人分配] initWithFirstName:名字姓氏:姓氏] autorelease],[[[自我分配] initWithFirstName:名字姓氏:姓氏] autorelease]会更合适。通过使用self,您将分配正确类型的对象,即存在人员子类。例如:[SpecialPerson personWithFirstName:@“Drew”lastName:@“McGhie”]将正确实例化一个特殊的人。 在“+”方法中,self指拥有该方法的类。 – 2009-07-13 20:48:57

关于firstname/lastName。

为清楚起见,您应该始终记住指定属性的属性。设置者的默认属性是,指定为,在这种情况下您要使用保留

@interface Person : NSObject 
{ 
    NSString *firstName; 
} 
@property (retain) NSString *firstName; 
@end 

随着保持每个只有一次使用点符号赋值编译器插入一个保留:只记得总是使用它。为了保持一致性我建议你写你的初始化是这样的:

- (id) initWithFirstName:(NSString*) aString 
{ 
    self.firstName = aString; 
} 

和dealloc方法是这样的:

- (void) dealloc 
{ 
    self.firstName = nil; 
} 

关于@ “” - 类型的对象。它们是不变的NSStrings对象。只要使用它们(它们是)NSString对象并从不释放它们。编译器会照顾它们。

NSString类是否作为赋值的一部分自动调用autorelease?

NSString类没有做任何事情,因为你没有发送消息。你所做的只是分配给一个变量。 NSString没有发现这个,它不是它的业务。

另外,这些陈述后面的两个* temp对象之间是否有区别?它们都包含相同的字符串,但它们在哪里有不同的内存/使用方式?

它们都是NSStrings,它们都包含相同的值,并且它们都被假定为不可变的。这就是你应该关心的一切。

其次,有了属性,我假设自动释放是自动处理的。如果我有这样的:

@property NSString *firstName; 
@property NSString *lastName; 

- (void) dealloc 
{ 
    //HERE!!!! 

    [super dealloc]; 
} 

我假设我不需要添加[firstName release][lastName release](在//HERE!!!!),因为这是自动的属性来处理。那是对的吗?

编号NSObject不会为您释放所有的属性值;你仍然需要在那里释放它们。

此外,不要做self.firstName = nilself.lastName = nildealloc。这些转换成消息(到你的访问器方法),当你在dealloc中这样做时,你发送消息给一个半对象。这是在惹麻烦。在init中用同样的方法来初始化属性值:使用你的属性/访问器将会发送消息到一半的对象。

使用@"String here"语法创建的NSString是常量字符串。这些与普通字符串不同。就像普通的C常量字符串一样,它们是在程序加载并存在的整个生命周期中创建的。它们所属的NXConstantString类将忽略所有内存管理消息。你可以retainrelease他们所有你喜欢的,它不会有任何区别。

对于使用[[NSString alloc] initWith...]类型方法创建的字符串,应用正常的memory management rules。我强烈建议阅读链接的文档 - 它们并不复杂,阅读完后,您几乎可以知道有关Cocoa内存管理的所有知识。