Ответ 1
Три способа dealloc
1. Просто отпустите
- (void)dealloc {
[airplane release];
[super dealloc];
}
Теперь ссылка на объект указывает на случайную позицию, которая может быть одной из двух вещей:
- Скорее всего это мусор, потому что позиция памяти не может быть интерпретирована как объект.
- Редко это будет другой объект, потому что память была повторно использована для создания нового объекта.
Эффект дальнейшего вызова метода через этот указатель - один из этих трех (один из них - undefined):
- Авария с
EXC_BAD_ACCESS
, потому что указатель указывает на мусор. - Сбой с селектором undefined, поскольку он указывает на допустимый объект, который не имеет этого метода.
- Успешное выполнение метода, поскольку новый объект имеет метод с тем же именем.
2. Release и nil
- (void)dealloc {
[airplane release], airplane = nil;
[super dealloc];
}
Теперь ссылка на объект равна нулю, и любые дальнейшие вызовы методов игнорируются. Это может привести к определенному, но непредвиденному боковому эффекту в вашем коде, но, по крайней мере, это не сбой вашего приложения.
3. Nil и релиз
- (void)dealloc {
id temp = airplane;
airplane = nil;
[temp release];
[super dealloc];
}
Это то же самое, что и раньше, но оно удаляет это маленькое окно между release и nil, где ссылка на объект указывает на недопустимый объект.
Какой из них лучше?
Это вопрос выбора:
- Если вы скорее сработали, выберите только выпуск.
- Если вы скорее проигнорируете ошибку, выберите nil + release или релиз + nil.
- Если вы используете
NSZombieEnabled=TRUE
, тогда просто отпустите, не нуль зомби!
Макросы и зомби
Простым способом отсрочки выбора является использование макроса. Вместо [airplane release]
вы пишете safeRelease(x)
, где safeRelease - это следующий макрос, который вы добавляете в целевой файл .pch:
#ifdef DEBUG
#define safeRelease(x) [x release]
#else
#define safeRelease(x) [x release], x=nil
#endif
Этот макрос не уважает зомби. Вот проблема: когда NSZombieEnabled
есть TRUE
, объект превращается в NSZombie
. Если вы потеряете ссылку на объект, любой вызов, отправленный ему, будет проигнорирован.
Чтобы исправить это, вот макрос из Кевин Баллард, который устанавливает указатель на недопустимую ссылку, ТОЛЬКО, когда NSZombieEnabled
- FALSE
. Это гарантирует сбой во время отладки, если зомби не включены, но в противном случае останутся зомби.
#if DEBUG
#define safeRelease(x) do { [x release]; if (!getenv("NSZombieEnabled")) x = (id)0xDEADBEEF; } while (0)
#else
#define safeRelease(x) [x release], x = nil
#endif
Ссылки
Apple не имеет рекомендации, по которой лучше. Если вы хотите прочитать мысли сообщества, здесь есть некоторые ссылки (темы комментариев тоже замечательные):
- Dealloc Джефф Ламарче
- Dont Coddle Your Code Даниэль Ялкут
- Подробнее о dealloc Джефф Ламарче
- Нуль, или не нуль, вот в чем вопрос Ching-Lan Huang
- Оборонительное кодирование в Objective-C Uli Kusterer