释放可可的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];
}
规则很简单:如果你有alloc
,copy
或retain
,这是你的责任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];通常是安全的选择,除非你知道它会包含一个自动释放的对象。
- 我从来没有发布像
NSString *foo = @"x";
字符串常量。从逻辑上讲,如果你不得不release
的结果,你将不得不release
参数initWithString
,并且这两个参数也要initWithFirstName:lastName:
。 - 您必须做
release
或autorelease
firstName
和lastName
。我已经看到了有关在析构函数中不使用属性语法的警告,我认为这与在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在评论中的反馈进行了更新。
而不是[[[个人分配] 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 = nil
和self.lastName = nil
在dealloc
。这些转换成消息(到你的访问器方法),当你在dealloc
中这样做时,你发送消息给一个半对象。这是在惹麻烦。在init
中用同样的方法来初始化属性值:使用你的属性/访问器将会发送消息到一半的对象。
使用@"String here"
语法创建的NSString是常量字符串。这些与普通字符串不同。就像普通的C常量字符串一样,它们是在程序加载并存在的整个生命周期中创建的。它们所属的NXConstantString类将忽略所有内存管理消息。你可以retain
和release
他们所有你喜欢的,它不会有任何区别。
对于使用[[NSString alloc] initWith...]
类型方法创建的字符串,应用正常的memory management rules。我强烈建议阅读链接的文档 - 它们并不复杂,阅读完后,您几乎可以知道有关Cocoa内存管理的所有知识。
我没有明确地分配/复制/保留firstName或lastName。这是否需要,因为alloc是通过综合自动生成来推断的,我只是在代码中看不到? – 2009-07-13 19:12:56
从某种意义上说。问题的关键在于你的对象拥有firstName和lastName,所以当它们被设置时,它就成为你释放它们的责任。 – 2009-07-13 19:29:02