Каков ваш предпочтительный стиль кодирования для 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];
   }

что я это делаю:)