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

Почему я не должен использовать Objective C 2.0-аксессоры в init/dealloc?

В @mmalc ответ на этот вопрос он утверждает, что "В общем, вы не должны использовать методы доступа в dealloc (или init)". Почему MMALC это говорит?

Единственные причины, о которых я могу думать, - это производительность и избегающие неизвестных побочных эффектов @dynamic seters.

Обсуждение

4b9b3361

Ответ 1

Все дело в использовании идиоматически согласованного кода. Если вы правильно структурируете свой код, есть множество правил, которые гарантируют, что использование accessor в init/dealloc безопасно.

Большая проблема заключается в том, что (как сказал mmalc) код, задающий состояние свойства по умолчанию, не должен проходить через аксессор, потому что он приводит к разным неприятным проблемам. Ловушка заключается в том, что нет причин, по которым init должен настроить состояние свойства по умолчанию. По ряду причин я перешел к аксессурам, которые инициализируются самостоятельно, как, например, простой пример:

- (NSMutableDictionary *) myMutableDict {
    if (!myMutableDict) {
        myMutableDict = [[NSMutableDictionary alloc] init];
    }

    return myMutableDict;
}

Этот стиль инициализации свойств позволяет отложить много кода инициализации, который фактически не может быть необходим. В приведенном выше случае init не несет ответственности за инициализацию состояния свойств, и он абсолютно безопасен (даже необходим) для того, чтобы использовать аксессоры в методе init.

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

Ответ 2

Это в основном рекомендация минимизировать вероятность ошибок.

В этом случае существует (возможность), что ваш сеттер/получатель может непреднамеренно делать прямые или косвенные предположения о состоянии объекта. Эти предположения могут быть проблемой, когда объект находится в процессе установки или уничтожения.

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

(Вы могли бы утверждать, что ваш объект должен удалить всех наблюдателей, прежде чем оторваться, что будет хорошей практикой, и другое руководство для предотвращения непреднамеренных проблем).

@implementation Example

-(void) setFoo:(Foo*)foo
{
   _foo = foo;
  [_observer onPropertyChange:self object:foo];
}

-(void) dealloc
{
   ...
   self.foo = nil;
}

@end

Ответ 3

Вы ответили на свой вопрос:

  • Производительность может быть вполне адекватной причиной сама по себе (особенно если ваши аксессоры являются атомарными).
  • Вам следует избегать любых побочных эффектов, которые могут иметь аксессоры.

Последнее особенно важно, если ваш класс может быть подклассом.

Не понятно, почему именно это адресовано именно в Objective-C 2 аксессуарах? Те же принципы применяются независимо от того, используете ли вы объявленные свойства или сами аксессоры для записи.

Ответ 4

Возможно, у установщика есть логика, которая должна выполняться, или, возможно, в реализации используется ivar с именем, отличным от геттера/сеттера или, возможно, двух иваров, которые должны быть выпущены и/или иметь значение, равное нулю. Единственный верный способ - вызвать сеттер. Ответ ответственен за сборщику таким образом, что нежелательные побочные эффекты не возникают при вызове во время init или dealloc.

Из Cocoa Design Patterns ", Buck, Yacktman, стр. 115:"... нет практической альтернативы использованию аксессуаров при использовании синтезированных переменных экземпляра с современной версией Objective-C или... "

Ответ 5

Фактически, для класса, который приходит и идет довольно часто (например, контроллер подробного представления), вы хотите использовать аксессор в init; в противном случае вы могли бы высвободить значение в viewDidUnload, к которому вы пытаетесь получить доступ позже (они показывают, что в CS193P...)

Ответ 6

Вы можете создавать те же проблемы, НЕ назначая установщик при распределении/освобождении.

Я не думаю, что вы можете добиться чего-либо, используя сохранение/выпуск непосредственно в init/dealloc. Вы просто изменяете набор возможных ошибок.

Каждый раз, когда вы должны думать о порядке распределения/освобождения имущества.