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

Objective-C синтезировать имя свойства переопределения

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

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

@property (retain, nonatomic) UILabel *dummyLabel;

И в файле реализации у меня есть:

@synthesize dummyLabel = _dummyLabel;

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

4b9b3361

Ответ 1

Да. self._dummyLabel - undefined, однако _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

Ответ 2

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

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

Ответ 3

Преимущество наличия другого имени для ivar, чем для свойства что вы можете легко увидеть в коде когда вы обращаетесь к одному или к другое - Andre K

Я не могу найти кнопку "comment", поэтому мне нужно отправить сообщение как "ответ".

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

Конечно, если вы делаете все правильно, вам, вероятно, не нужна помощь установщика, чтобы сохранить/освободить объекты правильно! Но могут быть и другие сценарии, когда ссылки на ваши ivars могут быть полезными, если 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 больше, чем просто семантическая.

Ответ 4

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

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

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

Ответ 5

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

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

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

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