Почему я должен писать [выпуск anView], anView = nil;а не [выпуск anView];?
-
03-07-2019 - |
Вопрос
Где-то я читал это - относительно предупреждений о нехватке памяти и отказа от невидимого представления со всеми его подпредставлениями (= целым пером, я думаю), вы должны сделать это:
-(void)dealloc {
[anView release], anView = nil;
[someImageView release], someImageView = nil;
[super dealloc];
}
скорее, чем
-(void)dealloc {
[anView release];
[someImageView release];
[super dealloc];
}
В чем причина привязки этих указателей к нулю (= «нет объекта») после того, как я вызываю выпуск?Дайте угадаю:Какой-то другой метод мог по какой-то причине сохранить представление (есть ли какой-нибудь пример, когда это могло произойти?), затем происходит событие DidReceiveMemoryWarning, и вы освобождаете целое представление пера+, которое в настоящее время не видно (т.е.в мультипросмотровом приложении).Как только пользователь захочет снова увидеть это представление, вы снова быстро загрузите наконечник, а затем:Он загружает все виды, подключает розетки и БАХ!Другие ваши сохраненные представления теперь висят без какого-либо указателя где-то одиноко в блоке памяти, что приводит к большой и глубокой утечке памяти, пока ваше приложение не выйдет из строя.
Правильно Неправильно?
Решение
вместо того, чтобы выполнять явный выпуск и устанавливать значение nil, если у ваших средств доступа есть свойства, связанные с ними, yoc, и выполните следующее как более краткий метод:
- (void) dealloc
{
self.retainedProperty1 = nil;
self.retainedProperty2 = nil;
self.copiedProperty = nil;
self.assignedProperty = nil;
}
таким образом вы можете иметь код с меньшим количеством повторений, поскольку синтезированный код позаботится о ваших релизах за вас.
Редактировать:Я должен отметить, что ваши свойства не могут быть доступны только для чтения, иначе по очевидным причинам вы получите ошибки компилятора :)
Другие советы
Этот принцип более общий, чем UIView.действительно, он более общий, чем Objective-C/Cocoa -release
метод.Это справедливо и для C malloc()
/free()
функции памяти.
Когда вам больше не нужен объект или какая-либо зона памяти, сначала вы отпускаете/освобождаете его.Затем, чтобы убедиться, что вы не будете использовать его снова, вы очищаете средства доступа к этому объекту или зоне памяти, назначая nil
к объекту или NULL
к указателю памяти.
Какой-то другой метод мог по какой-то причине сохранить представление.
Если вы не вызываете dealloc
самостоятельно, он вызывается только тогда, когда счетчик сохранения становится равным нулю.
Обратите внимание, что в Objective-C отправка сообщения nil
«объект» (часто) совершенно прекрасен.Это будет нет остановите вашу программу, но сообщение просто проигнорируется.Однако вы не можете отправить сообщение освобожденному объекту, что приведет к сбою.
Итак, следующее приведет к ошибке:
[anView release];
[anView doSomething];
Но на самом деле это нормально:
[anView release];
anView = nil;
[anView doSomething];
Это дело вкуса, но, учитывая вышеизложенное, вы, возможно, предпочтете аварийно завершить свою программу, а не задаваться вопросом, почему doSomething не выполняется...
Смотрите также Отправка сообщений в ноль от Apple Введение в язык программирования Objective-C 2.0.
Метод -dealloc вызывается, когда объект освобождается, и после этого никакие другие методы объекта выполняться не будут.Следовательно, установка любой переменной экземпляра в ноль не имеет никакого эффекта за пределами этого объекта.
Если бы вы выпускали объект (без использования установщика) где-то еще в классе, было бы важно установить для переменной экземпляра значение nil, чтобы код в другом месте не отправлял сообщение на этот адрес.
Я часто использую этот шаблон:
- (void) showHelp: (id) sender
{
if (helpController == nil)
{
helpController = [[HelpController alloc] initWithNibName: @"Help" bundle: [NSBundle mainBundle]];
}
[self presentModalViewController: helpController animated: YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
[helpController release];
helpController = nil;
}
Практически везде, где я выделяю модальный или иначе «временный» контроллер представления.Таким образом, он сохраняется, если он мне снова понадобится, но исчезает, если памяти становится мало.