Действительное использование аксессуаров в методах init и dealloc?
Я уже слышал из нескольких источников (stackoverflow.com, cocoa -dev, документация, блоги и т.д.), что "неправильно" использовать аксессоры и настройки (foo, setFoo:) в вашем init и dealloc. Я понимаю, что существует дистанционная возможность сбивать с толку другие объекты, которые наблюдают свойство, если вы это сделаете. (простой пример приведен ниже здесь)
Однако я должен сказать, что я не согласен с этой практикой по следующей причине:
Новая среда Objective-C (одна на iPhone и 64-битная среда выполнения в 10.5) позволяет объявлять свойства без объявления соответствующего ivar. Например, следующий класс будет компилироваться просто отлично на 10,5 или для iPhone (устройство, а не симулятор):
@interface Foo : NSObject { }
@property (retain) id someObject;
@end
@implementation Foo
@synthesize someObject;
@end
Понимая, что приведенное выше является вполне допустимым классом Objective-C, скажем, я решил написать инициализатор, а для целей управления памятью - метод dealloc (поскольку GC недоступен на iPhone). Все, что я когда-либо читал об инициализаторах и освобождении, заставил бы меня написать следующие два метода:
- (id) init {
if (self = [super init]) {
//initialize the value of someObject to nil
[self setSomeObject:nil];
}
return self;
}
- (void) dealloc {
//setting someObject to nil will release the previous value
[self setSomeObject:nil];
[super dealloc];
}
Однако, согласно документации и популярному мнению, это "неправильно". Поэтому мои вопросы таковы:
- Как я могу инициализировать someObject без использования доступа? Вы могли бы сказать, что компилятор (или среда выполнения или что-то еще) гарантирует, что someObject уже установлен на ноль, но я считаю, что было бы неправильным поведением полагаться на это. Имея приличный фон в C, я видел множество ошибок из-за неправильной инициализации переменных, и это кажется немного другим.
- Как я могу освободить someObject, если я не должен использовать accessor в методе dealloc?
Если ответ на любой из них - "вы не можете", то как плохо будет использовать аксессоры в ваших методах init и dealloc?
Ответы
Ответ 1
Я понимаю, что текущее поведение 10.5, при котором синтезированные ивары не доступны напрямую, Apple считает ошибкой; вы должны иметь возможность напрямую обращаться к нему, но не можете.
Следовательно, вы должны уметь:
someObject = nil;
вместо
self.someObject = nil;
Тем временем, использование аксессора напрямую - это единственный способ сделать это, не предоставляя явного ivar.
Обновление: эта ошибка исправлена; теперь вы можете сделать someObject = nil
просто отлично.
Ответ 2
EDIT (13 февраля 2013 г.): Как отмечалось в моем комментарии ниже, и особенно после добавления ARC, я изменил свое мнение об этом. До ARC я видел много ошибок, вызывающих сбои, из-за неправильных назначений ivar в init
. ИМО, особенно работая с младшими командами, редкие проблемы с использованием аксессуаров в init
были перевешены общими ошибками доступа к ivar. Поскольку ARC устраняет эти ошибки, ошибки, связанные с редким, но возможным, с использованием accessor в init
могут быть более важными, и поэтому я переключился на поддержку прямого использования ivars в init
и dealloc
, и только в тех местах; (возможно, вы не можете использовать аксессоры внутри самого аксессора).
Ответ PRE-ARC
Я категорически не согласен с теми, кто возражает против аксессоров в -init
. Практически во всех случаях это очень хорошее место для использования аксессуаров, и это избавляет от многих ошибок, которые я видел в новых кодах Cocoa, которые неизменно не сохраняются при назначении в -init
.
-dealloc
- более жесткий вызов. У меня есть естественная склонность использовать там аксессоров (чтобы они использовались повсюду), но это может вызвать головную боль из-за KVO (или даже NSNotifications, если вы публикуете уведомление об изменении в своем сеттере). Тем не менее, хотя я не использую accessors в -dealloc
, я считаю это очень спорным, и Apple очень несовместимо с этим (мы знаем, что они вызывают setView:
в UIViewController -dealloc
например).
В любом случае я бы сказал, что недоиспользование аксессуаров вызвало 100% ошибок чрезмерного использования. Я всегда буду ошибаться в использовании их, кроме случаев, когда есть веская причина не делать этого.