Освободить или установить на ноль удерживаемые элементы

Что лучше: установить для моих сохраненных переменных-членов значение ноль или освободить их, когда я убираю? Установка оставшейся переменной в nil кажется более безопасным способом освободить объект без риска двойного вызова для него.

Обновление: позвольте мне пояснить, что я имею в виду вары-члены, для которых установлено свойство сохранения, то есть:

@property (nonatomic, retain) SomeClass* mInstanceVar;

person Joey    schedule 18.03.2011    source источник
comment
Привет, Джоуи, если я ответил на твой вопрос, не забудьте отметить мой ответ как правильный! ;)   -  person Itai Ferber    schedule 19.03.2011


Ответы (2)


Лучше всего сначала освободить переменные экземпляра, а затем установить для них nil в вашем -dealloc методе. Мне лично нравится это делать вот так:

[myVar release], myVar = nil;

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


Если у вас есть переменная экземпляра, настроенная как таковая,

@property (retain) NSObject *myVar;

тогда не рекомендуется вызывать self.myVar = nil; во время освобождения. Если у вас есть объекты, которые зарегистрированы для уведомлений KVO в вашей переменной экземпляра, вызов self.myVar = nil отправит эти уведомления, и другие объекты будут уведомлены, что плохо, потому что они будут ожидать, что вы все еще будете в допустимом состоянии - вы не если вы находитесь в процессе освобождения.

Даже если они не зарегистрированы для уведомлений KVO, это все равно не лучшая идея, потому что вы никогда не должны вызывать методы, которые могут полагаться на состояние вашего объекта, когда его состояние несовместимо (некоторые переменные могут / не существовать), и вы просто следует самостоятельно справиться с этим процессом. [myVar release], myVar = nil; хватит.

Если вам нужна дополнительная информация, прочтите ответ Дэйва Делонга на this вопрос.


Для инициализации также нецелесообразно вызывать методы установки и получения свойств (во многом по той же причине, что и выше). В вызове -init вы должны настроить вышеупомянутую переменную как таковую:

myVar = nil; // If you want to set it up as nil.
OR
myVar = [[NSObject alloc] init]; // Or set it up as an actual object.

Избегайте self.myVar = nil и self.myVar = [[NSObject alloc] init в случаях, когда ваш класс находится в неопределенном состоянии (эти вызовы допустимы в -viewDidLoad и -awakeFromNib, потому что к этому моменту ваш класс был полностью инициализирован, и вы можете полагаться на то, что переменные экземпляра находятся в полное состояние).

person Itai Ferber    schedule 18.03.2011
comment
Я либо все еще в замешательстве, либо, возможно, неправильно сформулировал вопрос. Я хотел сказать, есть ли у меня свойство сохранения, установленное для моей переменной экземпляра. Я обновлю вопрос, чтобы отразить это. Если ваш ответ здесь относился к этому делу, не могли бы вы уточнить? Насколько я понимаю, переменная со свойством сохранения сохранит объект после установки с помощью '=', а затем, когда я сделаю = nil; он освободит этот объект. Это тот случай, о котором я спрашиваю здесь. - person Joey; 19.03.2011
comment
Я обновил свое объяснение. Если все еще непонятно, дайте мне знать, и я добавлю к этому. - person Itai Ferber; 19.03.2011
comment
Думаю, я понимаю ваше объяснение. Уместно ли тогда с контроллерами представления устанавливать очищенные переменные со свойством сохранения '= nil' в методе viewDidLoad, но вместо этого использовать [var release] в dealloc? (Это то, что я наблюдаю в их примерах, таких как пример ToolbarSearch.) - person Joey; 19.03.2011
comment
В методе -viewDidLoad можно использовать средства задания и получения свойств, потому что к этому моменту ваш класс полностью инициализирован. Однако делать это во время -init вызовов не рекомендуется по той же причине, что и dealloc вызовы. Я обновил свой ответ. - person Itai Ferber; 19.03.2011
comment
а если вы очень ленивы, есть макрос Three20 для выполнения шага release / nil ... если вы не используете Three20, просто напишите свой собственный макрос для этого. #define TT_RELEASE_SAFELY (__ POINTER) {[__POINTER выпуск]; __POINTER = ноль; } - person Stew; 19.03.2011
comment
Я был бы признателен тем, кто проголосовал против моего ответа, почему. Если в моем ответе есть проблема, я бы хотел ее исправить. - person Itai Ferber; 21.01.2012

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

Не забудьте также установить для всех ваших свойств nil во время dealloc.

person Cameron Hotchkies    schedule 18.03.2011