麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

ios6處理內(nèi)存警告

2019-11-14 20:14:00
字體:
供稿:網(wǎng)友

   iphone下每個app可用的內(nèi)存是被限制的,如果一個app使用的內(nèi)存超過20M,則系統(tǒng)會向該app發(fā)送Memory Warning消息。收到此消息后,app必須正確處理,否則可能出錯或者出現(xiàn)內(nèi)存泄露。

     app收到Memory Warning后會調(diào)用:UIapplication::didReceiveMemoryWarning -> UIApplicationDelegate::applicationDidReceiveMemoryWarning,然后調(diào)用當(dāng)前所有的viewController進(jìn)行處理。因此處理的主要工作是在viewController。

    當(dāng)我們的程序在第一次收到內(nèi)存不足警告時,應(yīng)該釋放一些不用的資源,以節(jié)省部分內(nèi)存。否則,當(dāng)內(nèi)存不足情形依然存在,iOS再次向我們程序發(fā)出內(nèi)存不足的警告時,我們的程序?qū)籭OS kill掉。

 

    iOS的UIViewController 類給我們提供了處理內(nèi)存不足的接口。在iOS 3.0 之前,當(dāng)系統(tǒng)的內(nèi)存不足時,UIViewController的didReceiveMemoryWarining 方法會被調(diào)用,我們可以在didReceiveMemoryWarining 方法里釋放掉部分暫時不用的資源。

    從iOS3.0 開始,UIViewController增加了viewDidUnload方法。該方法和viewDIdLoad相配對。當(dāng)系統(tǒng)內(nèi)存不足時,首先UIViewController的didReceiveMemoryWarining 方法會被調(diào)用,而didReceiveMemoryWarining 會判斷當(dāng)前ViewController的view是否顯示在window上,如果沒有顯示在window上,則didReceiveMemoryWarining 會自動將viewcontroller 的view以及其所有子view全部銷毀,然后調(diào)用viewcontroller的viewdidunload方法。如果當(dāng)前UIViewController的view顯示在window上,則不銷毀該viewcontroller的view,當(dāng)然,viewDidunload也不會被調(diào)用了。但是到了ios6.0之后,這里又有所變化,ios6.0內(nèi)存警告的viewDidUnload 被屏蔽,即又回到了ios3.0的時期的內(nèi)存管理方式。   


    iOS3-iOS5.0以前版本收到內(nèi)存警告:
調(diào)用didReceiveMemoryWarning內(nèi)調(diào)用super的didReceiveMemoryWarning會將controller的view進(jìn)行釋放。所以我們不能將controller的view再次釋放。
處理方法:
        

java代碼                          

  1. -(void)didReceiveMemoryWarning  
  2.        {  
  3.                 [super didReceiveMemoryWarning];//如沒有顯示在window上,會自動將self.view釋放。  
  4.                 // ios6.0以前,不用在此做處理,self.view釋放之后,會調(diào)用下面的viewDidUnload函數(shù),在viewDidUnload函數(shù)中做處理就可以了。  
  5.        }  
  6.        -(void)viewDidUnload  
  7.        {  
  8.               // Release any retained subviews of the main view.不包含self.view  
  9.               //處理一些內(nèi)存和資源問題。  
  10. 10.                [super viewDidUnload];  
  11. 11.                
  12. 12.        }  

 

 

    iOS6.0及以上版本的內(nèi)存警告:
調(diào)用didReceiveMemoryWarning內(nèi)調(diào)用super的didReceiveMemoryWarning調(diào)只是釋放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的宏開關(guān),保證是在6.0下使用的,6.0以前屏蔽以下代碼,否則會在下面使用self.view時自動加載viewDidUnLoad

            if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) {

             //需要注意的是self.isViewLoaded是必不可少的,其他方式訪問視圖會導(dǎo)致它加載 ,在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;// 目的是再次進(jìn)入時能夠重新加載調(diào)用viewDidLoad函數(shù)。
             }

           }
    }

 

但是似乎這么寫相對于以前并不省事。最終我們找到一篇文章,文章中說其實并不值得回收這部分的內(nèi)存,原因如下:

1. UIView是UIResponder的子類,而UIResponder有一個CALayer的成員變量,CALayer是具體用于將自己畫到屏幕上的。

2. CALayer是一個bitmap圖象的包裝類,當(dāng)UIView調(diào)用自身的drawRect時,CALayer才會創(chuàng)建這個bitmap圖象類。

3. 具體占內(nèi)存的其實是一個bitmap圖象類,CALayer只占48bytes, UIView只占96bytes。而一個iPad的全屏UIView的bitmap類會占到12M的大小!

4.在iOS6時,當(dāng)系統(tǒng)發(fā)出MemoryWarning時,系統(tǒng)會自動回收bitmap類。但是不回收UIView和CALayer類。這樣即回收了大部分內(nèi)存,又能在需要bitmap類時,根據(jù)CALayer類重建。

    所以,iOS6這么做的意思是:我們根本沒有必要為了幾十byte而費力回收內(nèi)存。

 

--------------------------切糕分割線--------------

PS:

1、關(guān)于這個的官方文檔:https://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html

2、zon2012貌似都沒有ios6的這個兼容(其實view是沒問題的,關(guān)鍵是資源)

 

分享到:  

xcode4.5(iOS 6)開發(fā)與之前的差異 | IOS發(fā)送Email的方法

評論

1 樓 嘯笑天 2013-05-14  

移動設(shè)備終端的內(nèi)存極為有限,應(yīng)用程序必須做好low-memory處理工作,才能避免程序因內(nèi)存使用過大而崩潰。

low-memory 處理思路
通常一個應(yīng)用程序會包含多個view controllers,當(dāng)從view跳轉(zhuǎn)到另一個view時,之前的view只是不可見狀態(tài),并不會立即被清理掉,而是保存在內(nèi)存中,以便下一次的快速顯現(xiàn)。但是如果應(yīng)用程序接收到系統(tǒng)發(fā)出的low-memory warning,我們就不得不把當(dāng)前不可見狀態(tài)下的views清理掉,騰出更多的可使用內(nèi)存;當(dāng)前可見的view controller也要合理釋放掉一些緩存數(shù)據(jù),圖片資源和一些不是正在使用的資源,以避免應(yīng)用程序崩潰。

思路是這樣,具體的實施根據(jù)系統(tǒng)版本不同而略有差異,本文將詳細(xì)說明一下iOS 5與iOS 6的low-memory處理。

iOS 5 的處理
在iOS 6 之前,如果應(yīng)用程序接收到了low-memory警告,當(dāng)前不可見的view controllers會接收到viewDidUnload消息(也可以理解為自動調(diào)用viewDidUnload方法),所以我們需要在 viewDidUnload 方法中釋放掉所有 outlets ,以及可再次創(chuàng)建的資源。當(dāng)前可見的view controller 通過didReceiveMemoryWarning 合理釋放資源,具體見代碼注釋。

舉一個簡單的例子,有這樣一個view controller:
@interface MyViewController : UIViewController {  
    NSArray *dataArray;  
}  
@property (nonatomic, strong) IBOutlet UITableView *tableView;  
@end 

對應(yīng)的處理則為:
#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Relinquish ownership any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
    self.tableView = nil;
    dataArray = nil;
    
    [super viewDidUnload];
}

iOS 6 的處理
iOS 6 廢棄了viewDidUnload方法,這就意味著一切需要我們自己在didReceiveMemoryWarning中操作。
具體應(yīng)該怎么做呢?

1.將 outlets 置為 weak
當(dāng)view dealloc時,沒有人握著任何一個指向subviews的強引用,那么subviews實例變量將會自動置空。
@property (nonatomic, weak) IBOutlet UITableView *tableView;

2.在didReceiveMemoryWarning中將緩存數(shù)據(jù)置空
#pragma mark -   
#pragma mark Memory management   
  
  
- (void)didReceiveMemoryWarning  
{  
    [super didReceiveMemoryWarning];  
    // Dispose of any resources that can be recreated.   
    dataArray = nil;  

不要忘記一點,每當(dāng)tableview reload 的時候,需要判斷一下 dataArray ,若為空則重新創(chuàng)建。

兼容iOS 5 與 iOS 6
好吧,重點來了,倘若希望程序兼容iOS 5 與 iOS 6怎么辦呢? 這里有一個小技巧,我們需要對didReceiveMemoryWarning 做一些手腳:
#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    
    if ([self isViewLoaded] && self.view.window == nil) {
        self.view = nil;
    }
    
    dataArray = nil;
}

判斷一下view是否是window的一部分,如果不是,那么可以放心的將self.view 置為空,以換取更多可用內(nèi)存。

這樣會是什么現(xiàn)象呢?假如,從view controller A 跳轉(zhuǎn)到 view controller B ,然后模擬low-memory警告,此時,view controller A 將會執(zhí)行self.view = nil ; 當(dāng)我們從 B 退回 A 時, A 會重新調(diào)用一次 viewDidLoad ,此時數(shù)據(jù)全部重新創(chuàng)建,簡單兼容無壓力~~

Note:
如果你好奇Apple為什么廢棄viewDidUnload,可以看看Apple 的解釋:
Apple deprecated viewDidUnload for a good reason. The memory savings from setting a few outlets to nil just weren’t worth it and added a lot of complexity for little benefit. For iOS 6+ apps, you can simply forget about view unloading and only implement didReceiveMemoryWarning if the view controller can let go of cached data that you can recreate on demand later.


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: www久久艹 | 亚洲欧美国产高清va在线播放 | 97久色| 免费国产人成网站 | 国产精品午夜一区 | 麻豆一区二区99久久久久 | 午夜视频免费在线观看 | 午夜爽爽爽男女免费观看hd | 国产一级一区 | 蜜桃91麻豆| 日本精品免费观看 | 免费在线观看成年人视频 | 一区国产在线 | 国产午夜亚洲精品 | 国产黄色一级大片 | 成人午夜激情网 | 久久老司机精品视频 | 最近免费观看高清韩国日本大全 | 日韩高清电影 | 91 在线免费观看 | 欧美日韩观看 | 在线看毛片的网站 | 精品在线观看一区 | 7777久久香蕉成人影院 | 91短视频在线 | 182tv成人福利视频免费看 | av在线免费观看网 | 黄色男女视频 | 欧美女孩videos | 欧美a区| 在线看毛片的网站 | 欧美日韩高清一区 | 久久国产成人精品国产成人亚洲 | 一区二区三区在线观看免费 | 国产91小视频在线观看 | 欧美成人一级片 | 激情97 | 999插插插 | 欧美成人二区 | 国产成人综合在线观看 | 久久精品.com |