我知道,如果你做下面的你肯定有内存泄漏:这是一个objective-c内存泄漏吗?
id foo = [[NSObject alloc] init];
foo = nil;
但是,如果你使用的是什么self.foo,有一个属性保留?而你的代码,而不是看起来如下:
foo = [[NSObject alloc] init];
self.foo = nil;
是仍然由于访问内存泄漏将其设置为nil前先释放内存?
我知道,如果你做下面的你肯定有内存泄漏:这是一个objective-c内存泄漏吗?
id foo = [[NSObject alloc] init];
foo = nil;
但是,如果你使用的是什么self.foo,有一个属性保留?而你的代码,而不是看起来如下:
foo = [[NSObject alloc] init];
self.foo = nil;
是仍然由于访问内存泄漏将其设置为nil前先释放内存?
self.foo = nil
将转化为
[nil retain]
[foo release]
foo = nil
没有内存泄漏在这里。
不,第二个例子不是内存泄漏。实际上,这就是我在dealloc
方法中处理retain
属性的方法。它只是更清洁。
你必须要小心的就是制作出的唯一的事情一定不要写
self.foo = [[NSObject alloc] init];
,否则你会双保留了对象,并使用了内存泄漏而告终。
我不这么认为做self.foo = nil
你基本上是使用setter和获得内存管理一起免费。
属性使你的代码看起来像赋值,但实际上它们与Obj-C 2.0之前自己写的传统存取器方法相同。使用属性Obj-C只是在后台为你生成访问器方法,而不是使用声明中指定的关键字(假设你使用@synthesize并且不要编写自己的访问器方法)。
不,没有内存泄漏。在第二个例子中的代码在逻辑上等同于
foo = [[NSObject alloc] init];
[nil retain];
[foo release];
foo = nil;
因为@synthesized二传手是logicall相当于
- (void)setFoo:(id)newFoo {
[newFoo retain];
[foo release];
foo = newFoo;
}
值得一提的是,设置foo
直接可能不是你想要的外面做些什么一个init方法。如果你直接把值赋给foo
,你跳过自动志愿的通知(你将不得不包装你的任务在willChangeValueForKey:/didChangeValueForKey:
对)和你打破任何的子类的行为,如果它覆盖setFoo:
方法,期待的foo
所有修改通过二传手。
您可以直接在init方法分配给foo
因为重写setFoo:
方法可能有副作用或取决于实例setFoo:
方法或子类的完全初始化。
同样,由于相同的原因,您将在-dealloc
方法中使用[foo release]
而不是self.foo = nil;
。
到目前为止的所有答案都假定第二个示例的第一行中的“foo
”是foo
属性后面的实例变量。这是默认行为。
如果foo
第一行指定的是局部变量,那么foo
属性是无关紧要的,除非稍后在方法中释放它,否则将泄漏该对象。
如果foo
是一个实例变量,但foo
财产实际上是由不同的实例变量的支持,或没有实例变量的话,那么(一)你正在编写难以维护的代码和(b)可以是泄漏。
最后,呼应以前的答案:如果foo
是实例变量后盾foo
属性,那么这是不是泄漏,因为setFoo:
方法,你在第二行调用将释放对象,你把foo
第一行中的实例变量。
由于没有人似乎已经注意到:还有可能是有泄漏。
我假设foo
既是伊娃和retain
属性:
@interface Foo : NSObject {
NSObject * foo;
}
@property (nonatomic, retain) NSObject * foo;
@end
比方说,你的代码看起来是这样的:
-(void)bar {
foo = [[NSObject alloc] init];
self.foo = nil;
}
也就是说,本身不漏提供foo
为零,以开头。这并不意味着它不会泄露 - 假设你添加一些代码:
-(void)baz {
self.foo = [[NSObject new] autorelease];
}
-(void)fubar {
[self baz];
[self bar];
}
像foo = [[Foo alloc] init]
的东西,因为它是假设你只叫他们的一个通常是init
- 方法安全,所以foo
是最初保证为nil
。在其他地方,你必须更加小心。
// Use assertions so it crashes debug builds if it's already set
assert(!foo);
foo = [[NSObject alloc] init];
self.foo = nil;
// Or release explicitly.
[foo release];
foo = [[NSObject alloc] init];
self.foo = nil;
// Or just use the setter, which will do the "right thing".
// This is particularly relevant for "copy" or "assign" accessors.
self.foo = [[[NSObject alloc] init] autorelease];
self.foo = nil;
请记住,使用dealloc中的属性通常会阻止访问方法更改为修改另一个ivar(可能已被释放)的情况。我只是使用发布。 – 2009-04-16 16:42:37