1. 程式人生 > >【ios6】viewDidUnload方法的離去和替代

【ios6】viewDidUnload方法的離去和替代

本篇文章為轉載,出處在末尾,copy之前,先說一下自己的總結:

viewDidUnload方法在ios6中已經被捨棄,好多人都說替代方法是Memory warning,可以直接在這個方法裡把一些ui屬性設定為nil,找了很多資料,我不這麼認為,所以總結就是:目前情況下,你可以不必再糾結在哪裡設定UI屬性=nil,在dealoc裡release掉就可以,不需要再考慮nil的問題,如果非要追求極致,那麼在dealoc裡release掉再=nil,也不是不可以。

在iOS6中,viewDidUnload回撥方法被Deprecated掉了。檢視蘋果的文件,可以看到如下的說明:


那麼,原本在viewDidUnload中的程式碼應該怎麼處理?在iOS6中,又應該怎麼處理記憶體警告?帶著這些問題,我查找了一些資料,在此分享給大家。

分析
在iOS4和iOS5系統中,當記憶體不足,應用收到Memory warning時,系統會自動呼叫當前沒在介面上的ViewController的viewDidUnload方法。通常情況下,這些未顯示在介面上的ViewController是UINavigationController Push棧中未在棧頂的ViewController,以及UITabBarViewController中未顯示的子ViewController。這些View Controller都會在Memory Warning事件發生時,被系統自動呼叫viewDidUnload方法。

在iOS6中,由於viewDidUnload事件在iOS6下任何情況都不會被觸發,所以蘋果在文件中建議,應該將回收記憶體的相關操作移到另一個回撥函式:didReceiveMemoryWarning 中。但是如果你僅僅是把以前寫到viewDidUnload函式中的程式碼移動到didReceiveMemoryWarning函式中,那麼你就錯了。以下是一個 錯誤的示例程式碼 :

1.- (void)didReceiveMemoryWarning {
2.    [super didReceiveMemoryWarning];
3.    if([self isViewLoaded] && ![[self view] window]) {
4.        [self setView:nil];
5.    }
6.}

這篇文章解釋了iOS6不推薦你將view置為nil的原因(連結開啟需要翻牆), 翻譯過來如下:

1.UIView有一個CALayer的成員變數,CALayer是具體用於將自己畫到螢幕上的。如下圖所示:


2.CALayer是一個bitmap圖象的容器類,當UIView呼叫自身的drawRect時,CALayer才會建立這個bitmap圖象類。

3.具體佔記憶體的其實是一個bitmap圖象類,CALayer只佔48bytes, UIView只佔96bytes。而一個iPad的全屏UIView的bitmap類會佔到12M的大小!

4.在iOS6時,當系統發出MemoryWarning時,系統會自動回收bitmap類。但是不回收UIView和CALayer類。這樣即回收了大部分記憶體,又能在需要bitmap類時,通過呼叫UIView的drawRect: 方法重建。

記憶體優化
另外文章中還提到蘋果的作業系統對此做的一個記憶體優化技巧,解釋如下:

當一段記憶體被分配時,它會被標記成“In use“, 以防止被重複使用。當記憶體被釋放時,這段記憶體會被標記成”Not in use”,這樣,在有新的記憶體申請時,這塊記憶體就可能被分配給其它變數。

CALayer包括的具體的bitmap內容的私有成員變數型別為CABackingStore, 當收到MemroyWarning時, CABackingStore型別的記憶體區會被標記成volatile型別(這裡的volatile和 C以及Java語言的volatile不是一個意思),volatile表示,這塊記憶體可能被再次被原變數重用。

這樣,有了上面的優化後,當收到Memoy Warning時,雖然所有的CALayer所包含的bitmap記憶體都被標記成volatile了,但是隻要這塊記憶體沒有再次被複用,那麼當需要重建bitmap記憶體時,它就可以直接被複用,而避免了再次呼叫 UIView的 drawRect: 方法。

總結
所以,簡單來說,對於iOS6,你不需要做任何以前viewDidUnload的事情,更不需要把以前viewDidUnload的程式碼移動到 didReceiveMemoryWarning方法中。

引用WWDC 2012 中的一段話來給viewDidUnload說再見:

The method viewWillUnload and viewDidUnload. We’re not going to call them anymore. I mean, there’s kind of a cost-benifit equation and analysis that we went through. In the early days, there was a real performance need for us to ensure that on memory warnings we unloaded views. There was all kinds of graphics and backing stores and so forth that would also get unloaded. We now unload those independently of the view, so it isn’t that big of a deal for us for those to be unloaded, and there were so many bugs where there would be pointers into。

 參考連結