Три способа решения сделки
1. Просто отпустите
- (void)dealloc {
[airplane release];
[super dealloc];
}
Теперь ссылка на объект указывает на случайную позицию, которая может быть одной из двух:
- Скорее всего, это мусор, потому что позиция памяти не может быть интерпретирована как объект.
- Редко это будет другой объект, потому что память была использована повторно для создания нового объекта.
Эффект дальнейших вызовов метода через этот указатель является одним из этих трех (который не определен):
- Сбой с
EXC_BAD_ACCESS
, потому что указатель указывает на мусор.
- Сбой с неопределенным селектором , поскольку он указывает на действительный объект, у которого нет этого метода.
- Успешное выполнение метода, поскольку у нового объекта есть метод с тем же именем.
2. Выпуск и ноль
- (void)dealloc {
[airplane release], airplane = nil;
[super dealloc];
}
Теперь ссылка на объект равна нулю, и любые дальнейшие вызовы методов игнорируются. Это может молча вызвать определенный, но непредвиденный побочный эффект в вашем коде, но, по крайней мере, это не приведет к сбою приложения.
3. Ноль и выпуск
- (void)dealloc {
id temp = airplane;
airplane = nil;
[temp release];
[super dealloc];
}
Это то же самое, что и раньше, но оно удаляет это маленькое окно между выпуском и нулем, где ссылка на объект указывает на недопустимый объект.
Какой из них лучше?
Это вопрос выбора:
- Если вы предпочитаете сбой, выберите просто отпустить.
- Если вы предпочитаете игнорировать ошибку, выберите nil + release или 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 нет рекомендации, какая из них лучше. Если вы хотите ознакомиться с мыслями сообщества, вот несколько ссылок (темы комментариев тоже великолепны):