1.如果能夠真正的了解autorelease,那麼才是了解了Objective c的記憶體管理。Autorelease實際上隻是把對release的調用延遲了,對于每一個Autorelease,系統隻是把該Object放入了當 前的Autorelease pool中,當該pool被釋放時,該pool中的所有Object會被調用Release。?
實際上對于 [NSString stringWithFormat:1.0] 這類構造函數傳回的對象都是autorelease的。
2. autorelease pool來避免頻繁申請/釋放記憶體(就是pool的作用了)。這個應該是相對比較好了解的。
總結:(1)一定要注意Autorelease pool的生存周期,了解Runloop,避免在對象被釋放後使用。
(2)[NSString stringWithFormat]這類函數傳回的對象是不需要再自己release的,它已經被autorelease了, 如果你想把它當一個全局對象使用,那必須自己再retain, 釋放時再release。
為什麼需要Auto release ?
這 個auto release有什麼好,象C/C++那樣,自己申請,自己釋放,完全可控不好麼, 這個auto relase 完全不可控,你都不知到它什麼時候會被真正的release。我的了解它有一個作用就是可以做到每個函數對自己申請的對象負責,自己申請,自己釋放,該函 數的調用者不需要關心它内部申請對象的管理。 在下面這個例子中,Func1的調用者不需要再去關心obj的釋放。
ClassA *Func1()
{
ClassA *obj = [[[ClassA alloc]init]autorelease];
return obj;
}
(1) 在Iphone項目中,大家會看到一個預設的Autorelease pool,程式開始時建立,程式退出時銷毀,按照對Autorelease的了解,豈不是所有autorelease pool裡的對象在程式退出時才release, 這樣跟記憶體洩露有什麼差別?
答案是,對于每一個Runloop, 系統會隐式建立一個Autorelease pool,這樣所有的release pool會構成一個象CallStack一樣的一個棧式結構,在每一個Runloop結束時,目前棧頂的Autorelease pool會被銷毀,這樣這個pool裡的每個Object會被release。
那什麼是一個Runloop呢? 一個UI事件,Timer call, delegate call, 都會是一個新的Runloop。例子如下:
NSString* globalObject;
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
globalObject = [[NSString alloc] initWithFormat:@"Test"];
NSLog(@"Retain count after create: %d", [globalObject retainCount]); // output 1.
[globalObject retain];
NSLog(@"Retain count after retain: %d", [globalObject retainCount]); // output 2.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(@"Retain count after Button click runloop finished: %d", [globalObject retainCount]);
// 輸出1. Button click loop finished, it's autorelease pool released, globalObject get released once.
}
-(IBAction)onButtonClicked
{
[globalObject autorelease];
NSLog(@"Retain count after autorelease: %d", [globalObject retainCount]);
// 輸出2。 Autorelease被call, globalObject被加如目前的AutoreleaePool。
}