Подтвердить что ты не робот

Действительное использование аксессуаров в методах 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?

4b9b3361

Ответ 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% ошибок чрезмерного использования. Я всегда буду ошибаться в использовании их, кроме случаев, когда есть веская причина не делать этого.