didReceiveMemoryWarning, viewDidUnload и dealloc - PullRequest
18 голосов
/ 21 февраля 2011

Я просмотрел много постов, моих книг и Apple Developer и почерпнул большую часть понимания, которое мне нужно для их использования.Я был бы очень признателен, если бы какой-нибудь добрый человек мог подтвердить, что я правильно понял (или поправил меня), а также ответить на два вопроса.

Большое спасибо,

Крис.

Порядок сообщений Обычно сообщения отображаются в следующем порядке:

  • didReceiveMemoryWarning

  • viewDidUnload (которая может быть вызвана 1) - очевидно, относится только к классам контроллера представления.

  • dealloc

didReceiveMemoryWarning

Вызывается, когда в системе недостаточно памяти.

По умолчанию контроллеры представления регистрируются для уведомлений о предупреждении памяти, а в методе шаблона вызов [super didReceiveMemoryWarning] освобождает представление, если у него нет суперпредставления, что является способом проверки, является ливид видимый или нет.Он освобождает представление, устанавливая его свойство равным nil.

Действие - освобождает все, что вам не нужно, вероятно, будет отменять то, что вы могли настроить в viewDidLoad.Не выпускайте элементы пользовательского интерфейса, так как они должны быть освобождены viewDidUnload.

Вопрос 1 - Кажется, что это будет вызвано, даже если представление является видимым, поэтому трудно увидеть то, что вы могли бы безопасно выпустить.Было бы очень полезно понять это и некоторые примеры того, что может быть освобождено.

viewDidUnload

Вызывается всякий раз, когда установлено невидимое свойство View контроллера представления.до нуля, вручную или чаще всего с помощью didReceiveMemoryWarning.

Существует метод viewDidUnload, так что вы можете: - очистить все, что захотите, сэкономить дополнительную память или - если вы сохранили некоторые IBOutlets,чтобы помочь освободить память, которая иначе не была бы освобождена при выгрузке представления.

Действие - как правило, любые IBOutlets, которые вы выпускаете в dealloc, также должны быть освобождены (и ссылки имеют значение nil) в этом методе.Обратите внимание, что если для свойств установлено сохранение, то установка их на nil также приведет к их освобождению.

dealloc

Вызывается, когда объект контроллера представления отменен,что будет, когда число сохранений упадет до нуля.

Действие - освободить все объекты, которые были сохранены классом, включая, но не ограничиваясь, все свойства с сохранением или копией.

Контроллеры и память Popping View

Вопрос 2 - Извлекает ли Popping view его из памяти?

Ответы [ 4 ]

31 голосов
/ 21 февраля 2011

Некоторые исправления и предложения:

  • didReceiveMemoryWarning практика

Как вы сказали, реализация контроллера по умолчанию didReceiveMemoryWarning освобождает его представление, если оно «безопасно»сделать это ».Хотя из документов Apple неясно, что означает «сделать это безопасно», это общепризнанно, поскольку у него нет суперпредставления (таким образом, представление не отображается в данный момент), а его метод loadView может перестроить все представление.без проблем.

Лучше всего при переопределении didReceiveMemoryWarning не пытаться вообще освобождать какие-либо объекты вида.Просто отпустите свои пользовательские данные, если они больше не нужны.Что касается представлений, просто позвольте реализации суперкласса разобраться с ними.

Иногда, однако, необходимость данных может зависеть от состояния вашего представления.В большинстве случаев эти пользовательские данные задаются методом viewDidLoad.В этих случаях «безопасно выпускать пользовательские данные» означает, что вы знаете, что loadView и viewDidLoad будут вызваны до того, как контроллер представления снова использует пользовательские данные.

Следовательно, в вашем didReceiveMemoryWarning,сначала вызовите реализацию суперкласса, и если его представление выгружено, то освободите пользовательские данные, потому что вы знаете, что loadView и viewDidLoad будут снова вызываться наверняка.Например,

- (void)didReceiveMemoryWarning {
    /* This is the view controller's method */
    [super didReceiveMemoryWarning];
    if (![self isViewLoaded]) {
        /* release your custom data which will be rebuilt in loadView or viewDidLoad */
    }
}

Будьте осторожны, чтобы не использовать self.view == nil, потому что self.view предполагает, что представление кому-то необходимо, и сразу же загрузит его снова.

  • viewDidUnload метод

viewDidUnload вызывается, когда контроллер представления выгружает представление из-за предупреждения памяти .Например, если вы удалите представление из суперпредставления и установите для свойства view контроллера значение nil, метод viewDidUnload будет вызываться , а не .Тонкий момент заключается в том, что даже если представление контроллера представления уже освобождено и установлено на ноль к тому времени, когда контроллер получает didReceiveMemoryWarning, так что на самом деле нет никакого представления для выгрузки для контроллера, viewDidUnload будет вызываться, если вывызовите реализацию суперкласса didReceiveMemoryWarning.

. Поэтому не рекомендуется вручную устанавливать для свойства view контроллера представления значение nil.Если вы это сделаете, лучше отправьте сообщение viewDidUnload.Я думаю, ваше понимание viewDidUnload более желательно, но, видимо, это не текущее поведение.

  • Контроллеры Popping View

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

Если вы имеете в виду выход из UINavigationController, это фактически уменьшает количество сохраняемых данных самого контроллера представления.Если контроллер представления не удерживается другим объектом, он будет освобожден, желательно с его представлением.Как я объяснил, viewDidUnload будет не вызываться на этот раз.

  • Другие ...

Технически, счет удержания может не идтидо нуля.Скорее всего, объект будет просто освобожден без предварительного обнуления счетчика.

Просто чтобы убедиться, что сам контроллер представления обычно не освобождается из-за поведения по умолчанию из-за предупреждения о памяти.

8 голосов
/ 21 февраля 2011

didReceiveMemoryWarning

...

Действие - освободите все, что вам не нужно, вероятно, будет отменено то, что вы могли настроить в viewDidLoad.

Это неправильно. Все, что вы воссоздаете в viewDidLoad, должно быть освобождено (и установлено в nil) в viewDidUnload. Как вы упоминаете ниже, didReceiveMemoryWarning также вызывается, когда вид является видимым. В didReceiveMemoryWarning вы должны освобождать такие вещи, как кеши или другие контроллеры представлений, за которые вы держитесь, которые могут быть лениво воссозданы в следующий раз, когда они потребуются (т. Е. Путем реализации их метода получения вручную).

viewDidUnload

...

Действие - как правило, любые IBOutlets, которые вы выпускаете в dealloc, также должны быть освобождены (и ссылки имеют значение nil) в этом методе. Обратите внимание, что если для свойств установлено сохранение, то установка их на ноль также приведет к их освобождению.

Правильно. Как правило, все, что вы создаете в viewDidLoad, и все IBOutlets, которые объявлены как retain, должны быть освобождены и установлены на nil здесь.

dealloc

...

Действие - освободить все объекты, которые были сохранены классом, включая, но не ограничиваясь, все свойства с сохранением или копированием.

Правильно. Стоит отметить, что сюда входят все объекты, которые вы обрабатываете в viewDidUnload, поскольку последний неявно вызывается в процессе dealloc (AFAIK, не совсем уверен). Вот почему важно установить все объекты релизов на nil в viewDidUnload, потому что в противном случае вы рискуете выпустить что-то дважды (сначала в viewDidUnload, затем снова в dealloc; если вы установите указатель на nil, Отмена вызова в dealloc не имеет никакого эффекта).

Контроллеры Popping View и память

Вопрос 2 - Удаление всплывающих окон из памяти?

Не обязательно. Это деталь реализации, о которой вам не следует беспокоиться. Какой бы ни была текущая практика, Apple может изменить ее в следующем выпуске.

3 голосов
/ 12 апреля 2013

Просто чтобы обновить эту ветку, чтобы она стала актуальной для iOS6:

viewDidUnload и viewWillUnload устарели в iOS6. Эти методы никогда не вызываются.

Для этого и других устаревших методов см .: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/DeprecationAppendix/AppendixADeprecatedAPI.html

0 голосов
/ 14 декабря 2015

Начиная с iOS 6, как мы можем проверить, загружен ли вид снова.Поскольку "viewDidUnload" устарела.Вы уверены, что «loadView» и «viewDidload» будут вызывать, если представление удаляется после предупреждения «didReceiveMemoryWarning».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...