2010-03-12 77 views
45

我已經開發了一個簡單的位置感知iPhone應用程序,除了手機的內存不足以外,它在功能上能夠很好地滿足我們的期望。如何實施didReceiveMemoryWarning?

在手機內存不足的情況下,我的應用程序崩潰了,如果我通過釋放一些空間來增加手機內存,它再次開始工作,沒有任何崩潰。

當我在這個問題上做了一些搜索時,我發現在低內存條件下,操作系統會發送didReceiveMemoryWarning給當前層次結構中的所有控制器,以便它們中的每一個都應該實現didReceiveMemoryWarning方法,並將iboutlet設置爲nil目前看不到的視圖。

我也讀過一些地方,如果該控制器的視圖不可見方法setView與nil參數將被調用,如果有一些插座變量附加到視圖將有問題在刪除它們。

所有這些fundas

那麼,什麼是最好的處理由執行didReceiveMemoryWarningviewDidUnload方法由iPhone引發低級別的內存狀態。

請給出一個適當的例子或鏈接,如果可能的話解決上述問題。

謝謝。

+0

http://stackoverflow.com/questions/491075/iphone-development-simulate-memory-warning – harshalb 2010-03-24 07:09:22

+0

典型的問題! – bobobobo 2013-11-04 19:40:12

回答

20

一個例子我張貼...我從somwhere複製...它可能給你一些想法...

- (void)didReceiveMemoryWarning { 

    // Release anything that's not essential, such as cached data (meaning 
    // instance variables, and what else...?) 

    // Obviously can't access local variables such as defined in method 
    // loadView, so can't release them here We can set some instance variables 
    // as nil, rather than call the release method on them, if we have defined 
    // setters that retain nil and release their old values (such as through use 
    // of @synthesize). This can be a better approach than using the release 
    // method, because this prevents a variable from pointing to random remnant 
    // data. Note in contrast, that setting a variable directly (using "=" and 
    // not using the setter), would result in a memory leak. 
    self.myStringB = nil; 
    self.myStringD = nil; 
    [myStringA release];// No setter defined - must release it this way 
    [myStringC release];// No setter defined - must release it this way 

    /* 3. MUST CONFIRM: NOT necessary to release outlets here - See override of 
     setView instead. 
    self.labelA = nil; 
    self.imageViewA = nil; 
    self.subViewA = nil; 
    */ 
    // Releases the view if it doesn't have a superview 
    [super didReceiveMemoryWarning]; 
} 
+0

嗨mihir我有iboutlets,我正在從nib文件加載我的視圖,只是檢查我的問題的評論。這是令人困惑的,因爲視圖不可見,那麼它會調用viewDidUnaload,所以我應該做什麼,使didReceiveMemoryWarning或viewDidUNload或setView中的值無效????????? – harshalb 2010-03-24 07:15:27

+0

但對每個視圖會有分隔didReceiveMemoryWarning功能,從而實現對於該特定視圖這種方法......在viewDidUnload方法使用相應的存取方法來設置對象零值... – 2010-03-24 07:40:12

+0

喜是U確認[ super didReceiveMemoryWarning];需要釋放對象後釋放 – 2013-02-14 05:53:18

5

didReceiveMemoryWarning決定做什麼取決於您。操作系統告訴你內存不足,你需要儘可能快地釋放內存。這個想法是,你應該釋放任何緩存的數據,卸載不可見的視圖等。細節是特定於應用程序的。

3

你也可以在didReceiveMemoryWarning釋放內存,您爲靜態分配變量在你的類中。因爲一旦分配了靜態變量的內存,它就不會在應用程序運行期間被釋放。

+1

本頁有一小段「內存警告」: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmNibObjects.html – schaechtele 2010-03-26 11:34:34

+0

this現在一天沒有發現任何其他的鏈接,而不是那 – codercat 2014-02-20 13:36:56

2

令我驚訝的是,官方iPhone樣本中僅有少數應用程序實現didReciveMemoryWarning。您可以使用iPhoneCoreDataRecipes示例作爲參考。

一些樣品(例如TableViewSuite)甚至做別的事情;-)

14

內存警告是一個信號,你,你應該配置哪些不是絕對關鍵的任何資源。大多數控制器將掛在數據緩存,中間數據或其他零碎上,通常用於保存重新計算。當他們收到內存警告時,他們應該開始沖洗他們不需要立即運行的任何東西。

你如何確定什麼是「關鍵」完全取決於你的應用程序的設計。例如,一個OpenGL遊戲可以確定當前在屏幕上的紋理是有價值的,並且是不可見的齊平紋理,或者在當前遊戲區域的邊界之外的水平數據。具有大量會話日誌的應用程序(如IRC客戶端)可能會將其從內存和磁盤中清除。

當你觀察,警告被髮送到每個控制器在您的層次結構,所以每一塊需要逐個確定哪些數據構成的「關鍵作業」和什麼是「消耗」。如果你已經對它們進行了優化,並且仍然出現內存不足的警告,那麼很遺憾你可以重新訪問核心應用程序設計,因爲你超出了硬件的限制。

+0

好吧,我已經通過使我的viewDidUnload方法中的零點出口我的解決方案。 – harshalb 2010-03-31 06:40:51

15

在iOS 5及更早版本上。

當控制器接收內存警告,didReceiveMemoryWarning會被調用。那時,如果控制器的視圖不在視圖層次結構中,視圖將被設置爲nil,並且viewDidUnload將被自動調用。所以我們在viewDidUnload中必須做的事情是釋放在viewDidLoad中創建的子視圖或從Nib創建的子視圖。像這樣:

- (void)viewDidUnload 
{ 
    self.subView = nil; 
    self.subViewFromNib = nil; 
} 

- (void)didReceiveMemoryWarning 
{ 
    self.someDataCanBeRecreatedEasily = nil; 
    [super didReceiveMemoryWarning]; 
} 

在iOS6上。

接收存儲器警告時,控制器不全自動釋放圖。所以viewDidUnload永遠不會被調用。 但是當memry警告發生時,我們仍然需要釋放我們的視圖(包括子視圖)。 喜歡這個。

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

請注意,在我們知道加載視圖之前,我們不會調用[self view]。導致這個方法會自動加載視圖,如果沒有加載視圖。

請注意,我們可以釋放剛視圖時不添加到窗口視圖。

+1

其實你可能想檢查'if(![self isViewLoaded] || [self.view window] == nil'')。無論是哪種情況,您都希望清理子視圖和其他內容。 – 2016-01-27 14:19:45