2010-03-12 3 views
45

Я разработал приложение для iPhone с удобным расположением, которое функционально отлично работает с нашими ожиданиями, за исключением низкого состояния телефона.Как реализовать didReceiveMemoryWarning?

В условиях низкой памяти телефона мое приложение просто падает, и если я увеличиваю память телефона, освобождая некоторое пространство, он снова начинает работать без какого-либо сбоя.

Когда я сделал некоторые проблемы с поиском по проблеме, я обнаружил, что в условиях низкой памяти ОС отправит didReceiveMemoryWarning всем контроллерам текущей иерархии, чтобы каждый из них должен реализовать метод didReceiveMemoryWarning, а также установить iboutlet на nil для представление, которое в настоящее время не видно.

Я также где-то читал, что если вид для этого контроллера не виден, будет вызван метод setView с параметром nil, и если есть некоторые переменные, связанные с представлением, будет проблема при их удалении.

Так со всеми этими Fundas, что лучше обрабатывать состояние памяти низкого уровня, поднятый Iphone, реализовав didReceiveMemoryWarning и viewDidUnload методы.

Пожалуйста, приложите пример или ссылку, если это возможно, для решения вышеуказанной проблемы.

спасибо.

+0

http://stackoverflow.com/questions/491075/iphone-development-simulate-memory-warning – harshalb

+0

Образец вопроса! – bobobobo

ответ

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

Hey mihir У меня есть iboutlets, и я загружаю свой взгляд из файла nib, просто проверяю комментарий по моему вопросу. Это сбивает с толку, поскольку представление не видно, тогда оно вызовет viewDidUnaload, чтобы я должен был свести значения к значениям в didReceiveMemoryWarning или viewDidUNload или setView ???????? – harshalb

+0

, но для каждого представления будет разделена функция didReceiveMemoryWarning, чтобы реализовать этот метод в отношении этого конкретного вида ... в методе viewDidUnload используйте соответствующий метод доступа, чтобы установить значение объекта в nil ... –

+0

Привет, вы уверены, что [ super didReceiveMemoryWarning]; необходимо положить после освобождения объектов –

5

Это зависит от вас, чтобы решить, что делать в didReceiveMemoryWarning. ОС говорит вам, что память низкая, и вам нужно как можно больше освободиться, как только сможете. Идея состоит в том, что вы должны освобождать любые кэшированные данные, выгружать просмотры, которые не видны, и т. Д. Детали специфичны для приложения.

3

Вы также можете освободить память в didReceiveMemoryWarning, что вы выделили для статического переменные в ваших классах. Поскольку после выделения памяти для статических переменных она не будет освобождена во время запуска приложения.

+1

Там крошечный пункт «Warnings памяти» на этой странице: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmNibObjects.html – schaechtele

+0

этой теперь дней не найдено никакой другой ссылки, а не – codercat

2

К моему удивлению, только несколько приложений в официальных образцах iPhone реализуют didReciveMemoryWarning. Вы можете использовать пример iPhoneCoreDataRecipes в качестве ссылки.

Некоторые образцы (например, TableViewSuite) даже сделать что-то еще ;-)

14

предупреждение памяти является сигналом к ​​вам, что вы должны избавиться от каких-либо ресурсов, которые не являются абсолютно необходимыми. Большинство ваших контроллеров будут висящими на кэшах данных, промежуточных данных или других битах и ​​фрагментах, часто для экономии перерасчета. Когда они получают предупреждения о памяти, они должны начать промывать все, что им не нужно немедленно для работы.

Как вы определяете, что является критическим, полностью зависит от дизайна вашего приложения. Например, игра OpenGL может определять, что текстуры в настоящее время на экране являются ценными и скрытыми текстурами, которые не видны, или данные уровня, которые находятся за пределами текущей области воспроизведения. Приложение с обширными сеансовыми журналами (например, IRC-клиент) может вывести их из памяти и на диск.

Как вы заметили, предупреждение отправляется каждому контроллеру в вашей иерархии, поэтому каждый фрагмент должен индивидуально определять, какие данные являются «критическими для работы» и что означает «одноразовые». Если вы оптимизировали их все и по-прежнему не понимаете предупреждения, к сожалению, время для пересмотра вашего основного дизайна приложения, потому что вы превысили пределы аппаратного обеспечения.

+0

OK Я сделал свое решение, установив точки вывода в моем методе viewDidUnload. – harshalb

15

На iOS 5 и ранее.

Когда контроллер получит предупреждение о памяти, будет вызван reReceiveMemoryWarning. В то время, если представление контроллера отсутствует в иерархии представлений, представление будет установлено на nil, и viewDidUnload будет автоматически вызван. Итак, вещи, которые мы должны делать в viewDidUnload, освобождают подзадачу, созданную в viewDidLoad или созданную из Nib. Пример:

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

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

На iOS6.

Контроллер не отключает автоматическое воспроизведение при получении предупреждения о памяти. Поэтому viewDidUnload никогда не будет вызван. Но нам еще нужно выпустить наш взгляд (включая под просмотр), когда произойдет предупреждение о воспоминаниях. Нравится это.

- (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)'. Вы хотите очистить свои подвид и другие вещи в любом случае. –