Objective-C синтезирует переопределение имени свойства - PullRequest
15 голосов
/ 27 сентября 2010

Я пытаюсь понять цель директивы synthesize с переопределением имени свойства.Скажем, у меня есть интерфейс, определенный следующим образом:

@interface Dummy ... {
    UILabel *_dummyLabel;
}

@property (retain, nonatomic) UILabel *dummyLabel;

И в файле реализации я имею:

@synthesize dummyLabel = _dummyLabel;

Из того, что я понимаю, "dummyLabel" это просто псевдонимпеременная экземпляра "_dummyLabel".Есть ли разница между self._dummyLabel и self.dummyLabel?

Ответы [ 5 ]

24 голосов
/ 27 сентября 2010

Да. self._dummyLabel не определено, однако _dummyLabel - нет.

Синтаксис Dot распространяется на простые вызовы методов, поэтому он не относится к свойствам. Если у вас есть метод с именем -(id)someObject, например, в случае object.someObject, он будет таким, как если бы вы написали [object someObject];.

self.dummyLabel  //works
self._dummyLabel //does not work
dummyLabel       //does not work
_dummyLabel      //works
[self dummyLabel];  //works
[self _dummyLabel]; //does not work
17 голосов
/ 27 сентября 2010

Ваше понимание неверно.dummyLabel является именем свойства и является , а не псевдонимом переменной экземпляра - переменная экземпляра только называется _dummyLabel.Таким образом, для экземпляра Dummy, называемого myObject, справедливо следующее:

  • [myObject dummyLabel] работает
  • myObject.dummyLabel работает
  • [myObject _dummyLabel] не удается
  • myObject._dummyLabel не удалось
  • myObject->dummyLabel не удалось
  • myObject->_dummyLabel зависит от видимости ивара (@public, @private, @protected)
  • [myObject valueForKey: @"dummyLabel"] работает
  • [myObject valueForKey: @"_dummyLabel"] зависит от реализации +accessInstanceVariablesDirectly (т.е. он будет работать в случае по умолчанию, где +accessInstanceVariablesDirectly возвращает YES).
13 голосов
/ 22 апреля 2011

Преимущество наличия другого имени для ивара, чем для свойства что вы можете легко увидеть в коде когда вы получаете доступ к одному или другое - Андре К

Я не могу найти кнопку «Комментарий», поэтому мне нужно опубликовать «ответ».

Просто хотел расширить комментарий Андре - зная, когда вы используете синтезированные свойства против переменной vanilla, вы знаете (особенно в случае с установщиками), когда переменная сохраняется / копируется / освобождается автоматически благодаря вашему хорошему установщику против манипулирования рукой.

Конечно, если вы все делаете правильно, вам, вероятно, не понадобится помощь установщика для правильного сохранения / освобождения объектов! Но могут быть и другие сценарии, в которых может быть полезна ссылка на ваши ивары как self.ivar вместо _ivar, например, когда вы используете собственные установщики / получатели вместо синтезированных по умолчанию. Возможно, каждый раз, когда вы изменяете свойство, вы также хотите сохранить его в NSUserDefaults. Поэтому у вас может быть такой код:

@interface SOUserSettings : NSObject {

BOOL _autoLoginOn;

}

@property (nonatomic, assign) BOOL autoLoginOn;

@end

@implementation SOUserSettings

@synthesize autoLoginOn = _autoLoginOn;

- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {

   _autoLoginOn = newAutoLoginOnValue;
   [[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"];
}

@end

Примечание: это просто иллюстративный код, с ним может быть что-то не так!

Итак, теперь в вашем коде, если у вас есть строка, которая говорит _autoLoginOn = YES - вы знаете, что она не будет сохранена в NSUserDefaults, тогда как если вы используете self.autoLoginOn = YES, вы точно знаете, что произойдет.

Разница между _autoLoginOn и self.autoLoginOn не просто семантическая.

0 голосов
/ 12 марта 2013

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

Есть хорошая статья от Apple: https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

Последний абзац:

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

0 голосов
/ 27 сентября 2010

Я не вижу большого преимущества переименования _dummyLabel в dummyLabel

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

Это также может быть полезно, если вам нужно поддерживать старый интерфейс с одним набором имен одновременно с новым набором API-интерфейсов с новым набором имен (setLastname vs. setSurname).

...