2009-04-30 2 views
7

Где-то я читал, что - относительно низких предупреждений памяти и отказавшись от без видимого вида со всеми его подвидами (= целое перо, я думаю), вы должны сделать это:Зачем писать [anView release], anView = nil; а не [anView release] ;?

-(void)dealloc { 
    [anView release], anView = nil; 
    [someImageView release], someImageView = nil; 

    [super dealloc]; 
} 

, а не

-(void)dealloc { 
    [anView release]; 
    [someImageView release]; 

    [super dealloc]; 
} 

В чем причина заземления этих указателей на nil (= "no object"), после того как я позвоню в релиз? Позвольте мне угадать: какой-то другой метод мог бы иметь -был вид по какой-то причине (кто-нибудь, например, когда это может произойти?), Тогда происходит операция didReceiveMemoryWarning, и вы отпускаете целое изображение nib +, которое в настоящее время не видно (т.е. в многопользовательском приложении). Как только пользователь захочет снова увидеть этот вид, вы быстро загрузите пинц, а затем: он загружает все виды, соединяет розетки и BANG! Теперь ваше другое видное видение висит без каких-либо указателей, где-то одиноко в кирпиче памяти, что приводит к полной и полной утечке памяти, пока ваше приложение не сработает.

Право/Неправильно?

ответ

1

, а не делать релиз expicit и установить на ноль, если ваши аксессоры имеют свойство, связанное с ними уосом и сделать следующее как более кратким способ:

- (void) dealloc 
{ 
    self.retainedProperty1 = nil; 
    self.retainedProperty2 = nil; 
    self.copiedProperty = nil; 
    self.assignedProperty = nil; 
} 

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

Edit: я должен указать на то, что ваши свойства не могут быть только для чтения, иначе вы получите ошибки компилятора по понятным причинам :)

+5

Нет. Это явно запрещено Apple и является хорошим способом вызвать сбой при некоторых обстоятельствах. См. Http://stackoverflow.com/questions/192721/why-shouldnt-i-use-obective-c-2-0-accessors-in-init-dealloc –

+0

Эта ссылка поднимает хороший момент, но все-таки это плохая идея, если вы используете ее только для свойств readwrite, которые полностью синтезированы? (это означает, что вы не декларируете синтез для свойства и по-прежнему переопределяете геттер или сеттер) – Kevlar

+0

Наверное, сейчас это прекрасно, с полностью синтезированными свойствами. Но Apple не гарантирует, что это разрешено, и рекомендует против него, так что это может сломаться в любом будущем SDK. –

14

Принцип более общий, чем UIView. действительно, он более общий, чем метод Objective-C/Cocoa -release. Это справедливо также с функциями памяти C malloc()/free().

Когда вам больше не нужен объект или какая-либо зона памяти, сначала вы освободите его/освободите. Затем, чтобы убедиться, что вы не будете использовать его снова, вы очищаете средства доступа к этому объекту или зоне памяти, назначая nil объекту или NULL указателю на память.

+4

+1. Главное состоит в том, что разыменование нулевого указателя прерывает выполнение немедленно, тогда как отсрочка указателя на уже освобожденную память может «работать» в течение некоторого времени и приводит к неприятным ошибкам. – zoul

+0

Спасибо. Мне интересно, почему мы так редко видим эту модель в примерах кода. Я никогда не видел его в коде Apple. Но мне кажется разумным сделать это, и я думаю, это не повредит. – Thanks

+0

Примерный код редко следует лучшим практикам. цель большинства примеров кода - продемонстрировать принцип, api или метод, насколько это возможно. – m4rkk

11

Some other method could have -retain'ed the view for some reason

Если вы не вызывая dealloc себя, это только называется, когда сохранить счетчик становится равным нулю.

Обратите внимание, что в Objective-C, отправляющем сообщение в nil, «объект» (часто) отлично. Выполнение этого будет не сделать вашу программу остановленной, но сообщение просто игнорируется. Однако вы не можете отправить сообщение освобожденному объекту, что приведет к сбою.

Итак, следующий даст вам сообщение об ошибке:

[anView release]; 
[anView doSomething]; 

Но это на самом деле ОК:

[anView release]; 
anView = nil; 
[anView doSomething]; 

Это дело вкуса, но выше, вы могли бы в факт предпочитает сбой вашей программы, а не интересно, почему doSomething не выполняется ...

См. также Sending Messages to nil от Apple Introduction to The Objective-C 2.0 Programming Language.

2

я использовать этот шаблон много:

- (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; 
} 

Практически везде, что я выделить ViewController, что является модальным, или иначе «временный». Таким образом, он зависает, если мне это нужно снова, но уходит, если память становится низкой.

4

Метод -dealloc вызывается, когда объект освобождается, и после него никакие другие методы не будут выполняться после. Поэтому установка любой переменной экземпляра в nil не имеет эффекта вне этого объекта.

Если вы освобождаете объект (без использования сеттера) где-то еще в классе, было бы важно установить переменную экземпляра равным nil, чтобы предотвратить перемещение кода в другом месте от сообщения на этот адрес.

+1

«никакие другие методы для объекта не будут выполнены после« - +1 »для этого ясного объяснения очевидного. Благодаря! (Что касается «важно установить переменную экземпляра в nil, чтобы предотвратить отправку кода в другом месте от другого сообщения на этот адрес», мне интересно, почему игнорирование непреднамеренного сообщения предпочтительнее получения сообщения об ошибке ...) – Arjan

+3

Поскольку все программы содержат ошибки - даже проверенные, выпущенные клиенту. Типы ошибок, возникающих при отправке сообщений в nil (в основном без-op), обычно менее серьезны, чем ошибки, возникающие при отправке сообщения освобожденному объекту. Первые обычно приводят к логическим ошибкам, когда программа работает не так, как предполагалось, последняя приведет к сбою. Во время разработки аварии приветствуются, поскольку они позволяют обнаружить ошибку - не так для выпущенных продуктов. – m4rkk

Смежные вопросы