iPhone相機和內存警告

如今咱們愈來愈習慣於在程序中使用相機。可是,幾乎在程序每次打開相機的瞬間,咱們都會收到一個「Received memory warning. Level=1」內存警告 。對於iOS來講,內存永遠是稀缺資源 ,所以,在你使用iPhone的高分辨率相機時,尤爲須要當心。程序員

程序員應當重視內存警告並對之進行處理,包括:緩存

1、在viewDidUnload方法中釋放內存spa

從iOS3.0開始, 釋放內存的代碼didReceiveMemoryWarning 遷移到了viewDidUnload中,咱們不用覆蓋didReceiveMemoryWarning方法。 事實上有不止地方會收到內存警告,所以程序中會有兩個地方存在 didReceiveMemoryWarning方法:AppDelegate 和ViewController。通常,咱們選擇在ViewController而不是AppDelegate中處理內存警告。.net

當程序收到內存警告時,程序員們就必須注意了。iOS隨後會自動清理當前「無用的」內存,好比內存中那些不處於頂層的ViewController和視圖。rest

 

咱們通常須要在viewDidUnload方法中,釋放視圖中無用的對象,好比UILabel、UIButton、NSArray等:orm

-(void)viewDidUnload對象

{圖片

     [super viewDidUnload];內存

   if(ivBg)[ivBg release],ivBg=nil;資源

    if(btSend)[btSendrelease],btSend=nil;

    if(btUpload)[btUploadrelease],btUpload=nil;

    if(vwBody)[vwBodyrelease],vwBody=nil;

    if(backButton)[backButtonrelease],backButton=nil;

    if(indicator)[indicatorrelease],indicator=nil;

    if(imagePicker)[imagePickerrelease],imagePicker=nil;

    if(receiverVC)[receiverVCrelease],receiverVC=nil;

}

注意,咱們釋放的對象必須是「無用的」。這些東西多是任何對象,好比成員對象和UI對象。關鍵在於怎樣認識一個對象是「有用的」仍是「無用的」。實際上,對於iOS來講,任何在viewDidUnload方法中釋放的東西都是「無用的」。若是你有任何對象在恢復視圖時會用到,那麼就不要在viewDidUnload方法中釋放。例如,用戶在視圖中的輸入——一封郵件的正文,或者用戶正在編輯的圖片——這些東西將在當相機使用完畢,iOS準備恢復視圖時顯示給用戶。

若是你確實不得不節省出更多的內存,那麼你能夠在viewDidUnload中把一些有用的東西也釋放掉,前提是,當你收到內存警告時,把這些對象持久化(保存到文件)。

而有的對象,它們原本就在xib文件中存在。在iOS恢復視圖時,這些東西會從xib中恢復到內存(initWithNibName->viewDidLoad)。好比按鈕、圖片、靜態標籤等UI對象。這些對象咱們就能夠看做是「無用的」,在viewDidUnload方法中能夠絕不客氣地把它們通通釋放。

2、在 didReceiveMemoryWarning 方法中設置內存警告標誌

如今,雖然咱們已經在viewDidUnload方法中,而不用在 didReceiveMemoryWarning方法中釋放對象,但didReceiveMemoryWarning方法仍然有一個用途,就是設置內存警告變量,以讓程序員知道什麼時候收到內存警告。

首先聲明一個BOOL成員做爲是否收到過內存警告的標誌:

BOOLmaybeSetViewNil;

而後在didReceiveMemoryWarning方法中:

maybeSetViewNil=YES;

3、在viewDidUnload方法中,保存視圖數據以便恢復

在第一步中,咱們提到爲了「儘量地」爲iOS騰出內存,咱們能夠把全部對象釋放,但對於「有用的」的對象,咱們應該採用必要的保存策略,好比保存到文件緩存中。

仍然在viewDidUnload方法中,加入如下代碼:

NSMutableDictionary*d=[[NSMutableDictionary alloc]init];

   

//"in use" objects

    if(tfTitle){

        if(tfTitle.text) [d setObject:tfTitle.text forKey:@"tfTitle.text"];

       self.tfTitle=nil;

    }

    if(lbAttach){

        if(lbAttach.text) [d setObject:lbAttach.text forKey:@"lbAttach.text"];

       self.lbAttach=nil;

    }

    if(imageView){

        if(imageView.image) {

           NSData* data=UIImageJPEGRepresentation(imageView.image,0.7);

           if (data)[d setObject:data forKey:@"imageView.image"];

        }

       self.imageView=nil;

    }

    if(receivers){

        [dsetObject:receivers forKey:@"receivers"];

       [receivers release],receivers=nil;

    }

    if(selectedPeople){

        [dsetObject:selectedPeople forKey:@"selectedPeople"];

       [selectedPeople release],selectedPeople=nil;

    }

[VCCachesaveToCache:d toVC:self];

    [d release];

 

能夠看到,咱們把全部「有用的」對象放到了Dictionary集合中。CCache是一個自定義類,我用它把Dictionary保存到指定文件。

4、恢復視圖狀態

接下來咱們能夠在viewDidLoad方法中恢復視圖狀態了:

selectedPeople=[[NSMutableArrayalloc]init];

    receivers=[[NSMutableStringalloc]init];

    if (maybeSetViewNil) {

       NSLog(@"maybe set view nil!");

       NSDictionary* d=[VCCache loadCache:self];

        if(d!=nil) {// status restore

           id obj=[d objectForKey:@"tfTitle.text"];

           if(obj!=nil)tfTitle.text=(NSString*)obj;

           

           obj=[d objectForKey:@"lbAttach.text"];

           if(obj!=nil)lbAttach.text=(NSString*)obj;

           

           obj=[d objectForKey:@"imageView.image"];

           if(obj!=nil)imageView.image=[UIImage imageWithData:(NSData*)obj];

           

⋯⋯

           

           obj=[d objectForKey:@"receivers"];

           if(obj!=nil)[receivers setString:(NSString*)obj];

           

           obj=[d objectForKey:@"selectedPeople"];

           if(obj!=nil)[selectedPeople setArray:(NSArray*)obj];

       }

       maybeSetViewNil=NO;

    }

注意,receivers和selectedPeople對象要在viewDidLoad方法中初始化,而不能在initWithNibName方法中初始化,不然對一個nil對象賦值是無效的。由於iOS在恢復視圖時從loadView方法開始調用,而不是從initWithNibName方法(參考前面的圖)。

相關文章
相關標籤/搜索