【內存管理】:誰應該寫在viewDidUnload裏,誰應該寫在dealloc裏,arc之後viewDidUnload怎麼用

viewDidUnload方法

  • 當系統內存吃緊的時候會調用該方法(注:viewController沒有被dealloc)

  • 內存吃緊時,在iPhone OS 3.0之前didReceiveMemoryWarning是釋放無用內存的唯一方式,但是OS 3.0及以後viewDidUnload方法是更好的方式

  • 在該方法中將所有IBOutlet(無論是property還是實例變量)置爲nil(系統release view時已經將其release掉了)

  • 在該方法中釋放其他與view有關的對象、其他在運行時創建(但非系統必須)的對象、在viewDidLoad中被創建的對象、緩存數據等

  • release對象後,將對象置爲nil(IBOutlet只需要將其置爲nil,系統release view時已經將其release掉了)

  • 一般認爲viewDidUnload是viewDidLoad的鏡像,因爲當view被重新請求時,viewDidLoad還會重新被執行

  • viewDidUnload中被release的對象必須是很容易被重新創建的對象(比如在viewDidLoad或其他方法中創建的對象),不要release用戶數據或其他很難被重新創建的對象


關於dealloc的官方說明,看的實在是蒙,這裏就不貼了。

----------------------------------------------------------------------------------------------------------------------------------------------------------

 viewDidUnload 和 dealloc 的區別,關於這兩者的區別的文章很多,但是大都是摘抄和翻譯官方文檔,有的也只是簡單的說兩句,並沒有詳細說出兩者具體的區別。

在瞭解兩者之間的區別,首先要知道 view 的生命週期,google 裏面有很多文章,可以先去搜一下,這裏就不詳解了。

顧名思義 viewDidUnload 就是當 view 被卸載以後執行的語句,它與 viewDidLoad 是相互呼應的。大家都知道官方的解釋是執行類似
    
self.myOutlet = nil;

的命令,但是爲什麼這麼幹,什麼時候調用這個方法呢?

這個方法是當應用程序接收到手機內存警告的時候自動調用的方法,目的就是清空內存除當前 viewController 以外,所有已經加載過的 viewController裏面的,暫時不再使用的一些控件或數據,以避免應用程序應消耗內存過多被強制關閉。記住,是除當前正在展示的 view 所屬 viewController 以外,所有已經在內存裏面的 viewController ,執行 viewDidUnload 方法,而不是當前 viewController 執行 viewDidUnload,當然,這些 viewController 不會被 dealloc。所以在 viewDidUnload 裏面一般都是釋放 IBOutlet 變量和在 viewDidLoad、viewWillAppear、viewDidAppear 等方法能夠重建的數據。而由其他頁面傳遞過來的數據或者無法經過 viewDidLoad、viewWillAppear、viewDidAppear 等方法重建的數據則不能釋放,舉例子說如果在 navigationController 由上一個頁面傳遞過來的一張圖片,在 viewDidUnload 裏被釋放的話,則當 view 再次加載的時候就無法恢復了。

那爲什麼要寫成 self.myOutlet = nil; ,實際上這個語法是執行了 property 裏的setter 方法

如果變量定義成retain的話,如:@property (nonatomic, retain) NSArray *dataArray; 它的set實現方法如下:

-(void) setDataArray:(NSString *)newArray{

    if(newArray !=dataArray){

         [dataArray release];

        dataArray =[newArray retain];

    }

}

它幹了兩件事:1、舊數據release 掉,2、新數據nil  retain,當然對 nil retain 是無意義的,也是沒問題的。

如果寫成 myOutlet = nil,那就是簡單的把 myOutlet 指向 nil,這樣內存就泄漏了,因爲老數據沒有 release。

而如果僅僅寫成 [myOutlet release] 也會有問題,因爲當 view 被 dealloc 的時候會 再次 release,程序就出錯了,

而對 nil release 是沒有問題的。

(在Nil上調用方法:   在Objective-C中,nil對象的作用等同於其他語言的NULL指針。不同的地方在於,在nil上調用方法不會導致程序崩潰或拋出異常。
 
dealloc 是當前 viewController 被釋放的時候,清空所有當前 viewController 裏面的實體和數據來釋放內存,該方法也是自動調用的。舉例說明當 modalView 被 dismissModalViewControllerAnimated 或者 navigationController 回到上一頁的時候,這個方法就會被自動調用。因爲這個頁面已經不再使用了,所以可以把所有實體和數據都釋放(release)掉。

其實兩者最大的區別就是: viewDidUnload 是內存除當前的viewController,其他所有 viewController 同時執行,而 dealloc 只是當前 viewController 執行。這個是網上的材料沒有說明的。

個人拙見,不對之處還請提正!

PS: 很多朋友都說無法調試 viewDidUnload,其實是可以的。方法是在 iOS 模擬器的菜單裏選 硬件 -> 模擬內存警告,這個時候就可以看到 viewDidUnload 裏面 NSLog 的東西了,可以試試在打開過的 viewController 裏都 NSLog 一下看看效果。而 dealloc 裏面可以直接 NSLog。


http://www.cocoachina.com/bbs/read.php?tid=83737

----------------------------------------------------------------------------------------------------------------------------------------------------------

問題一誰應該release


What should be released in viewDidUnload is:

1. IBOutlet properties

2. Anything that will be recreated in viewDidLoad


這個說法不一定對

----------------------------------------------------------------------------------------------------------------------------------------------------------



內存使用的N個建議


用 [str setStr:nil] 來代替 [str release] 更好,可消滅野指針,和C++是一樣的道理。?

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

以上是轉載的一位哥們的鏈接:http://blog.csdn.net/pinklpig/article/details/7364762

寫的非常好,但是看了還有一個問題:使用了arc之後,爲什麼viewDidUnload還是需要調用?

因爲在內存緊張的時候,編譯器並不知道哪些內存是需要釋放的,哪些是不需要釋放的,所以還是需要自己手動來管理內存。

如果視圖銷燬的時候,編譯器就知道所有的內存都是需要釋放的,編譯器就自動釋放所有內存。所以dealloc方法就不需要了。



dealloc 方法

另外啓用 ARC 之後,dealloc 方法在大部分時候都不再需要了,因爲你不能調用實例對象的 release 方法,也不能調用[super dealloc]。假如原先的dealloc 方法只是釋放這些對象,Xcode 就會把 dealloc 方法完全移除。你不再需要手動釋放任何實例變量。

如果你的 dealloc 方法處理了其它資源(非內存)的釋放,如定時器、CoreFoundation 對象,則你仍然需要在 dealloc 方法中進行手動釋放,如 CFRelease(),free()等。這時 Xcode 會保留 dealloc 方法,但是移除所有的 release 和[superdealloc]調用。如下:

- (void) dealloc

{

AudioServicesDisposeSystemSoundID(soundID);   


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章