В Objective-C на iOS, что такое (стиль) различие между "self.foo" и "foo" при использовании синтезированных геттеров?

Я искал много вопросов об объектах ObjC и синтезированных аксессуарах безрезультатно. Этот вопрос больше связан с вопросом "помогите мне решить вопрос"; Я не ожидаю ответа, но я скорее ищу экспертов для взвешивания аргументов.

В классе Cocoa Touch я бы написал такой код (где soundEffects - синтезированное свойство NSArray):

id foo = [self.soundEffects objectAtIndex:1];

Коллега попросил меня объяснить, почему выше это лучше, чем эта строка:

id foo = [soundEffects objectAtIndex:1];

Ну, функционально, это ничем не отличается.

Мои аргументы для первого:

  • self.soundEffects указывает каждому другому кодеру, работающему над кодом, что это iVar, а не локальная область.

  • Если нам когда-либо понадобится, мы могли бы поместить пользовательскую логику в аксессуар soundEffects getter.

  • По какой-то конкретной причине он "чувствует", как правильно, что нужно делать после работы в Obj-C в течение года.

Он принимает аргументы # 1 и # 2 как действительные, но также дает контрапункт:

  • Разве это не просто раздувание кода?

  • Не следует ли разрешать классу напрямую общаться со своими iVars без необходимости вызова метода (getter) на себя?

Любые участники?

Ответы

Ответ 1

Ваша точка 1 не совсем правильная: self.soundEffects не является ivar, хотя может случиться, что вы получите что-то, что есть, как в случае с вашим синтезированным NSArray, на данный момент.

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

Это также хорошая практика при использовании мутатора, поэтому вы поддерживаете постоянное управление памятью.

По большей части, я бы сказал, что желательно пройти через self.property для всего, что является свойством, и ограничить прямой доступ к IVAR для вещей, которые являются строго внутренними. Тем не менее, я признаю, что в некоторых случаях - особенно для вещей, которые не используют семантику retain/copy - это может быть больше предпочтений стиля.

Ответ 2

Я лично решил использовать префикс подчеркивания для ivars, и этот вид синтеза

@synthesize name = _name;

Таким образом я не смешиваю их. Основная проблема не в том, что я использую сам, так это то, что этот код

_name = ...

сильно отличается от

self.name = ...

Когда @property использует опцию сохранения. Первый не сохраняет объект, а второй вызывает синтезированный сеттер, который сохраняет.

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

Ответ 3

используя что-то вроде self.variable = nil, переменная переходит через свой сеттер и, следовательно, получает доступную память. если вы просто используете variable = nil, например, в методе dealloc, это вызовет утечку, поскольку на самом деле он не проходит через синтезированный сеттер для переменной и не уменьшает счетчик сохранения. См. Это сообщение утечка памяти с самим собой.

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

Ответ 4

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

Также согласно ios 6, ivar, соответствующий

@property (nonatomic)NSArray *propertyName;

будет

_propertyName

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

id foo = [soundEffects objectAtIndex:1];
больше. Не уверен, хотя. Вместо этого вы должны использовать
id foo = soundEffects[1];