2010-01-25 3 views
11

Я знаю, что дискуссии о стилях кодирования, как правило, заканчиваются катастрофой и бесконечными пламенными войнами, но это не то, что я хочу достичь. В течение последнего десятилетия я в основном видел два разных стиля кодирования для методов dealloc в Objective-C. Первым и наиболее распространенным было размещение dealloc в нижней части файла. Это также стиль, который Apple использует в шаблонах по умолчанию Xcode. Логика этого, похоже, заключается в том, что dealloc вызывается, когда приближается конец объекта, поэтому конец файла кажется приятной метафорой.Каков ваш предпочтительный стиль кодирования для dealloc в Objective-C?

С другой стороны, пара людей, как правило, ставит dealloc непосредственно под директивами @synthesize. Это имеет два основных недостатка, на мой взгляд:

  1. В верхней части файла захламляется расточной код.
  2. Труднее найти основные части вашего класса, вам нужно прокрутить вниз.

Огромное преимущество, на мой взгляд, заключается в том, что у вас есть прямая визуальная связь между свойствами и соответствующим сообщением release.

Другое дело в том, что уже выпущены уже выпущенные переменные. Хотя я не думаю, что это необходимо, особенно в контексте объекта, где вся переменная получает desctructed после завершения dealloc, я также склоняюсь к нулю переменных. Я привык делать это для переменных в области функций, поэтому я просто согласен с моим стилем кодирования.

Это, как большинство моих классов выглядит следующим образом:

@implementation Bar 

@synthesize foo; 

- (void)dealloc 
{ 
    [foo release], foo = nil; 

    [super dealloc]; 
} 

// Initializers and other methods… 

я уже упоминал пару плюсов и минусов. Что вы думаете об этой теме? Какой стиль кодирования вы используете в dealloc и почему? Есть ли другие плюсы и минусы, о которых я забыл упомянуть?

Я не хочу начинать пламенную войну здесь. Я просто хочу знать, какой стиль вы используете, и если у вас есть конкретные причины для этого или если это не важно для вас в конце.

+0

Eventho Вы не хотите, чтобы люди начали обсуждения и пламя, это произойдет с такими вопросами. – Younes

ответ

16

Мне нравится поставить реализацию dealloc прямо под инициализаторами. Таким образом, когда я добавляю новую переменную экземпляра, я помню release это сразу после того, как я .

Кроме того, мне очень полезно использовать директиву #pragma mark, чтобы упростить просмотр файла. Поэтому я «группирую» методы init и dealloc вместе под заголовком «инициализаторы». При просмотре файла, имея эти заголовки, намного легче найти то, что вы ищете, не отвлекаясь на метод dealloc.

Это может быть скучный код, но человек важен.

+0

Я обертываю инициализатор (ы) + dealloc в один знак #pragma - жизненный цикл объекта (сродни шаблонам Apple «просмотр жизненного цикла» для UIViewController) –

5

Я положил свой dealloc наверху, только под директивами @synthesize. Это немного неуклюжий и скучный код, но очень важный код, поэтому он получает лучший биллинг. Кроме того, жизненно важно иметь возможность сравнивать свойства и ссылки.

-1
- (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]; 
    } 

это так, как я это :)

+4

Я уверен, что stringWithFormat возвращает объект с автореализацией. Вам нужно сохранить его в init и release в dealloc. Кроме того, ваши фигурные скобки не балансируют ... – walkytalky

+0

читайте пожалуйста, что-то вроде следующего не должно быть выпущено, как я заявляю в своем комментарии в коде. Что я имел в виду, так это то, что объект, который я использую там, автореализован. –

+0

Отправка сообщений для себя внутри dealloc - это, по крайней мере, очень плохая практика! –

10

Не установить Ивар к нулю в dealloc, если у вас нет особых причин для. Это нецелесообразно и в лучшем случае маскирует ошибки программиста, которые вам лучше узнать, чем скрывать.

+1

+1: Не устанавливая переменные экземпляра в 'nil' и используя хороший ol' 'NSZombieEnabled, я обнаружил несколько логических ошибок за годы, которые я никогда бы не нашел иначе. – Alex

3

Я положил его на дно. Это позволяет мне просто ударить в конец и перейти к нему, когда я добавляю то, что нужно освободить. Я также не хочу, чтобы это было вокруг моих синтезаторов свойств, потому что это обманчиво. Не все, что у меня есть, обязательно имеет прикрепленный к нему синтезированный аксессуар. Черт, это даже не обязательно все в инициализаторе. Если я попытаюсь использовать ярлык таким образом, я, вероятно, испорчу его.

+1

Согласовано. Я ссылаюсь на все переменные-члены в '@ interface', когда я пишу' dealloc'. –

+0

Кроме того, наконец, возможность определить блок ivar в камнях @implementation (но я все еще продолжаю прыгать в заголовок и обратно). –

8

Мой заказ:

  1. Синтезы и @dynamic директивы (я начал делать это на вершине когда-то в 2011 году, ранее, они были с реализациями аксессоры)
  2. методов класса (+load, +initialize, +sharedFoo, другие)
  3. инициализаторы
  4. dealloc
  5. finalize
  6. Пользовательские реализации аксессоры
  7. методы на соответствие
  8. протокола, сгруппированных в соответствии с протоколом (обычно с #pragma mark директивы)
  9. методы обработки уведомлений (как правило, объявленные в расширении класса вверх в верхней части)
  10. Другие способы (как правило, объявленные в расширение класса на вершине)

в методе dealloc:

  • Не используйте сообщения о доступе, неявные (права доступа к свойствам) или явные. Любой нечистый пользовательский аксессор может быть небезопасным для вызова частично освобожденного объекта. (То же самое касается инициализаторов.)
  • Не устанавливайте ivars на nil. Объект частично освобожден; почему вы все еще отправляете сообщения? (Если вы этого не сделали, тогда ничего не смотрит на значения иваров.)
  • (Если было бы целесообразно установить ivars на nil) Не злоупотребляйте оператором запятой. Выражение типа [foo release], foo = nil смешивает типы (сначала void из выражения сообщения, затем id из выражения присваивания). Это отдельные заявления; пишите их как таковые.

  • [super dealloc] всегда последний и всегда имеет пустую строку над ним, подчеркивая его присутствие.

Конечно, у меня также есть «Обработать предупреждения как ошибки», поэтому, если я забуду [super dealloc], я сломаю свою сборку.

+1

Это много хороших советов по улучшению стиля кодирования Objective-C. Спасибо, что поделились ими. Я знаю, что бессмысленно указывать указатели на 'nil' после освобождения их в' dealloc'. Я просто делаю это, потому что я привык делать это в контексте метода. Я также использую пустую строку над '[super dealloc]', чтобы подчеркнуть важность. Интересно, что вы синтезируете свои свойства между методами. У вас есть конкретная причина для этого? –

+1

Это исторический артефакт: перед свойствами все аксессоры были обычными, и я не всегда объявлял их в заголовке. Таким образом, определение было бы первым, когда компилятор услышал о них, поэтому я не мог использовать их раньше или компилятор правильно пожаловал бы об этом. Таким образом, эти необъявленные аксессоры должны были быть определены до того, что могло бы их использовать. Теперь я синтезирую почти все мои аксессоры, но мой выбор места размещения продолжается. –

+0

В настоящее время я синтезирую вверху реализации, как раз под любыми явными переменными экземпляра. Таким образом, все переменные экземпляра, явные и синтезированные, объединены и доступны во всем классе, в том числе в инициализаторах и 'dealloc'. –

Смежные вопросы