我知道,如果你做下面的你肯定有內存泄漏:這是一個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