我读到的关于objective-c内存管理的所有内容都让人觉得难以置信。用大家的意思来说:“释放你分配,保留或复制的任何内容”。但我认为还有一些更具体的案例并不那么明确。以下是一些示例情况。每种方法的正确程序是什么:
情况#1:
Foo *foo = [[foo alloc] init];
Foo *fooToo = [[[foo alloc] init] autorelease];
foo = fooToo;
在将foo分配给fooToo之前是否需要释放它?
情况#2 当我做以下事情时,我似乎遇到了很多崩溃: (.h和.m为了方便而混在一起)
Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;
-(id)init{
self = [super init];
}
-(void)dealloc{
[super dealloc];
[foo release];
}
我经常被告知“总是以dealloc释放你为什么设置保留属性”。但如果像我所示的那样完成,这将会崩溃。
情况#3 类似的情况也会崩溃: (.h和.m为了方便而混在一起)
Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;
-(id)init{
self = [super init];
self.foo = nil;
}
-(void)dealloc{
[super dealloc];
[foo release];
}
由于某些原因,当我的代码归结为dealloc时,foo不是== nil。
情况#4 最后,只是一个问题,人们在决定
时使用什么样的一般思维过程 self.foo = bar;
和
foo = bar;
当宣布foo与上述情况相同时? self.foo
只是另一种编码方式:
foo = [bar retain]
;
答案 0 :(得分:6)
情况#1:
是的,您需要在失去对它的引用之前释放foo
。鉴于您已分配它,您有责任释放它。如果您在发布之前重新分配foo
,则无法再释放它!
情况#2:
dealloc
的正确实施是:
- (void)dealloc {
[foo release];
[super dealloc];
}
dealloc
方法需要调用超级dealloc
方法而不是release
方法。此外,您需要在调用[super dealloc]
情况#3: 与情况#2相同。
情况#4:
我总是喜欢使用self.foo = bar
,因为如果需要,它会自动执行以下步骤:
foo
bar
foo
分配给bar
作业foo = bar
和foo = [bar retain]
不会释放foo
的上一个对象。
答案 1 :(得分:4)
等待。停止。 Msaeed的答案是正确的,逐行的,但没有强调真正的问题。
你要么像计算机一样思考,要么每行代码都假设太多魔法。
请不要把它视为一种侮辱 - 这是一个非常容易犯的错误,这是一个几乎每个程序员在新环境中做出的错误(我在开始使用Objective-C时做了一些非常神奇的假设) 1989)。
让我们重新考虑一下情况。
情况#1: ...删除不相关的代码...
foo = fooToo;
这是一个简单的任务。无论在此之前包含的foo
- 对您案例中的对象的引用 - 现在都会被fooToo
的值覆盖。没有魔力。没有额外的方法执行或涉及的代码行。
如果foo
包含对该行代码保留对象的引用。引用将被覆盖。如果在覆盖引用之前需要release
foo
,请执行此操作,但这与分配正交。
情况#2: ...删除不相关的代码...
-(void)dealloc{
[super dealloc];
[foo release];
}
玩电脑;你要求super dealloc然后假设一个实例变量在super被释放后有效。坏消息。吊杆。
这里没有魔力。 foo
是对实例变量的引用到 self。 -dealloc
会破坏自我,因此foo
不再有效。
(我相信静态分析仪会抓住它。如果没有,它应该。)
情况#3:
见#2。这是完全相同的问题。您正在访问不再有效的实例的实例变量。
情况#4:
self.foo = bar;
完全相同:
`[self setFoo:bar];
(禁止任何背叛者=恶作剧)
因此,关键的区别在于-setFoo:的实现 - 手写或@synthesized。在你的情况下,它retain
s吧。这与foo = bar;
不同,因为没有保留发生;它只是对bar
的引用的赋值。
我强烈建议您重新访问Objective-C介绍文档。这会有所帮助。但是,我还鼓励您退后一步,真正思考上述情况中每行代码的作用。没有魔力,实际行为非常简单。