iPhone下每一個app可用的內存是被限制的,若是一個app使用的內存超過20M,則系統會向該app發送Memory Warning消息。收到此消息後,app必須正確處理,不然可能出錯或者出現內存泄露。html
app收到Memory Warning後會調用:UIApplication::didReceiveMemoryWarning -> UIApplicationDelegate::applicationDidReceiveMemoryWarning,而後調用當前全部的viewController進行處理。所以處理的主要工做是在viewController。java
當咱們的程序在第一次收到內存不足警告時,應該釋放一些不用的資源,以節省部份內存。不然,當內存不足情形依然存在,iOS再次向咱們程序發出內存不足的警告時,咱們的程序將會被iOS kill掉。ios
iOS的UIViewController 類給咱們提供了處理內存不足的接口。在iOS 3.0 以前,當系統的內存不足時,UIViewController的didReceiveMemoryWarining 方法會被調用,咱們能夠在didReceiveMemoryWarining 方法裏釋放掉部分暫時不用的資源。app
從iOS3.0 開始,UIViewController增長了viewDidUnload方法。該方法和viewDIdLoad相配對。當系統內存不足時,首先UIViewController的didReceiveMemoryWarining 方法會被調用,而didReceiveMemoryWarining 會判斷當前ViewController的view是否顯示在window上,若是沒有顯示在window上,則didReceiveMemoryWarining 會自動將viewcontroller 的view以及其全部子view所有銷燬,而後調用viewcontroller的viewdidunload方法。若是當前UIViewController的view顯示在window上,則不銷燬該viewcontroller的view,固然,viewDidunload也不會被調用了。可是到了ios6.0以後,這裏又有所變化,ios6.0內存警告的viewDidUnload 被屏蔽,即又回到了ios3.0的時期的內存管理方式。 函數
iOS3-iOS5.0之前版本收到內存警告: 調用didReceiveMemoryWarning內調用super的didReceiveMemoryWarning會將controller的view進行釋放。因此咱們不能將controller的view再次釋放。 處理方法: code
-(void)didReceiveMemoryWarning { [super didReceiveMemoryWarning];//如沒有顯示在window上,會自動將self.view釋放。 // ios6.0之前,不用在此作處理,self.view釋放以後,會調用下面的viewDidUnload函數,在viewDidUnload函數中作處理就能夠了。 } -(void)viewDidUnload { // Release any retained subviews of the main view.不包含self.view //處理一些內存和資源問題。 [super viewDidUnload]; }
iOS6.0及以上版本的內存警告: 調用didReceiveMemoryWarning內調用super的didReceiveMemoryWarning調只是釋放controller的resouse,不會釋放view 處理方法: -(void)didReceiveMemoryWarning { [super didReceiveMemoryWarning];//即便沒有顯示在window上,也不會自動的將self.view釋放。 // Add code to clean up any of your own resources that are no longer necessary.
// 此處作兼容處理須要加上ios6.0的宏開關,保證是在6.0下使用的,6.0之前屏蔽如下代碼,不然會在下面使用self.view時自動加載viewDidUnLoad視頻
if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) {htm
//須要注意的是self.isViewLoaded是必不可少的,其餘方式訪問視圖會致使它加載 ,在WWDC視頻也忽視這一點。接口
if (self.isViewLoaded && !self.view.window)// 是不是正在使用的視圖 { // Add code to preserve data stored in the views that might be // needed later. // Add code to clean up other strong references to the view in // the view hierarchy. self.view = nil;// 目的是再次進入時可以從新加載調用viewDidLoad函數。 }內存
} }
可是彷佛這麼寫相對於之前並不省事。最終咱們找到一篇文章,文章中說其實並不值得回收這部分的內存,緣由以下:
1. UIView是UIResponder的子類,而UIResponder有一個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類時,根據CALayer類重建。
因此,iOS6這麼作的意思是:咱們根本沒有必要爲了幾十byte而費力回收內存。
--------------------------切糕分割線--------------
PS:
一、關於這個的官方文檔:https://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html
二、zon2012貌似都沒有ios6的這個兼容(其實view是沒問題的,關鍵是資源)