Каков ваш предпочтительный стиль кодирования для dealloc в Objective-C?
Я знаю, что дискуссии о стилях кодирования, как правило, заканчиваются катастрофой и бесконечными пламенными войнами, но это не то, что я хочу достичь. В течение последнего десятилетия я в основном видел два разных стиля кодирования для методов dealloc
в Objective-C. Первым и наиболее распространенным было размещение dealloc
в нижней части файла. Это также стиль, который Apple использует в шаблонах по умолчанию Xcode. Логика этого, похоже, заключается в том, что dealloc
вызывается, когда приближается конец объекта, поэтому конец файла кажется хорошей метафорой.
С другой стороны, пара людей обычно ставит dealloc
непосредственно под директивами @synthesize
. На мой взгляд, это два основных недостатка:
- Верхняя часть файла заполняется скучным кодом.
- Сложнее найти основные части вашего класса, вам нужно прокрутить вниз.
Огромное преимущество, на мой взгляд, заключается в том, что у вас есть прямая визуальная связь между свойствами и соответствующим сообщением release
.
Другое дело - niling уже выпущенные переменные. Хотя я не думаю, что это необходимо, особенно в контексте объекта, где вся переменная получает desctructed после окончания dealloc
, я также склоняюсь к нулю переменных. Я использовал это для переменных в области функций, поэтому я просто согласен с моим стилем кодирования.
Вот как выглядит большинство моих классов:
@implementation Bar
@synthesize foo;
- (void)dealloc
{
[foo release], foo = nil;
[super dealloc];
}
// Initializers and other methods…
Я уже упомянул пару плюсов и минусов. Что вы думаете об этой теме? Каков стиль кодирования, который вы используете в dealloc
и почему? Есть ли другие плюсы и минусы, о которых я забыл упомянуть?
Я не хочу начинать здесь пламенную войну. Я просто хочу знать, какой стиль вы используете, и если у вас есть конкретные причины для этого, или если это не важно для вас в конце.
Ответы
Ответ 1
Мне нравится внедрять реализацию dealloc
прямо под инициализаторами. Таким образом, когда я добавляю новую переменную экземпляра, я помню release
сразу после я init
.
Кроме того, мне очень полезно использовать директиву #pragma mark
, чтобы упростить просмотр файла. Поэтому я группирую методы init
и dealloc
вместе под заголовком "инициализаторы". При просмотре файла, имея эти заголовки, намного легче найти то, что вы ищете, не отвлекаясь на метод dealloc
.
Это может быть скучный код, но человеку это важно.
Ответ 2
Не устанавливайте свой ivar на nil в dealloc, если у вас нет конкретной причины. Это нецелесообразно и, в лучшем случае, маскирует ошибки программиста, которые вам лучше узнать, чем скрывать.
Ответ 3
Мой заказ:
- Синтезы и директивы
@dynamic
(я начал делать это наверху в 2011 году, раньше они были с реализациями с доступом)
- Методы класса (
+load
, +initialize
, +sharedFoo
, другие)
- Инициализаторы
-
dealloc
-
finalize
- Пользовательские реализации аксессуаров
- Методы согласования протоколов, сгруппированные по протоколу (обычно с директивами
#pragma mark
)
- Методы обработчика уведомлений (обычно объявляются в расширении класса вверху)
- Другие методы (обычно объявленные в расширении класса вверху)
В рамках метода dealloc
:
- Не использовать сообщения о доступе, неявные (доступ к свойствам) или явные. Любой нечистый пользовательский аксессор может быть небезопасным для вызова частично освобожденного объекта. (То же самое касается инициализаторов.)
- Не устанавливайте ivars на
nil
. Объект частично освобожден; почему вы все еще отправляете сообщения? (Если вы этого не сделаете, тогда ничто не смотрит на значения иваров.)
- (Если было бы целесообразно установить ivars на
nil
) Не злоупотреблять оператором запятой. Выражение типа [foo release], foo = nil
смешивает типы (сначала void
из выражения сообщения, затем id
из выражения присваивания). Это отдельные заявления; пишите их как таковые.
-
[super dealloc]
всегда последний и всегда имеет над ним пустую строку, подчеркивая ее присутствие.
Конечно, у меня также есть "Treat Warnings as Errors", поэтому, если я забуду [super dealloc]
, я сломаю свою сборку.
Ответ 4
Я положил свой dealloc наверху, только в соответствии с директивами @synthesize. Это немного неуклюжий и скучный код, но очень важный код, поэтому он получает лучший биллинг. Кроме того, жизненно важно иметь возможность сравнивать свойства и ссылки.
Ответ 5
Я положил его внизу. Это позволяет мне просто ударить в конец и перейти к нему, когда я добавляю то, что нужно освободить. Я также не хочу, чтобы это было вокруг моих синтезаторов свойств, потому что это обманчиво. Не все, что у меня есть, обязательно имеет прикрепленный к нему синтезированный аксессуар. Черт, это даже не обязательно все в инициализаторе. Если я попытаюсь использовать ярлык таким образом, я, вероятно, испорчу его.
Ответ 6
- (id)init{
self = [super init];
if( self ) {
someVar = [[NSMutableArray alloc] init];
// something like the following shouldn't be released:
someString = [NSString stringWithFormat:@"ANumber: %d",10];
}
return self;
- (void)dealloc{
[someVar release]; someVar = nil;
[super dealloc];
}
что я это делаю:)