Переопределение имени свойства синтеза Objective-C
-
25-09-2019 - |
Вопрос
Я пытаюсь понять цель synthesize
директива с переопределением имени свойства.Скажем, у меня есть интерфейс, определенный следующим образом:
@interface Dummy ... {
UILabel *_dummyLabel;
}
@property (retain, nonatomic) UILabel *dummyLabel;
И в файле реализации у меня есть:
@synthesize dummyLabel = _dummyLabel;
Насколько я понимаю, «dummyLabel» — это просто псевдоним переменной экземпляра «_dummyLabel».Есть ли разница между self._dummyLabel и self.dummyLabel?
Решение
да. self._dummyLabel
не определено, однако _dummyLabel
не является.
Точечный синтаксис расширяется до простых вызовов метода, поэтому он не специфичен для свойств. Если у вас есть метод под названием -(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
Другие советы
Ваше понимание неверно. 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
).
Преимущество наличия другого имени для Ивара, чем для собственности, заключается в том, что вы можете легко увидеть в коде, когда вы получаете доступ к одному или другому - Andre K
Я не могу найти кнопку «комментарий», поэтому я должен публиковать как «ответ».
Просто хотел расширить комментарий Andre - знаком, когда вы используете синтезированные свойства, против ванильной переменной, вы знаете (особенно в случае с больницами), когда переменная сохраняется / копируется / выпущена автоматически благодаря вашему приятному сеттелю, VS манипулировать вручную.
Конечно, если вы делаете все правильно, вам, вероятно, не нужна помощь сеттера, чтобы исправить / высвобождать объекты правильно! Но тоже могут быть другие сценарии, где относятся к вашим иверам как self.ivar
вместо _ivar
Может быть полезен, например, когда вы используете пользовательские посетители / GetTers вместо синтезированных по умолчанию. Возможно, каждый раз, когда вы измените свойство, вы также хотите хранить его в 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
это больше, чем просто семантика.
Я не вижу никаких больших преимуществ переименования _DummyLabel в Dummylabel
В некоторых objc runtimes у вас есть трудные временные переменные экземпляра невидимы для пользователей класса. Для них придерживаясь префикса (или суффикса) на вашу переменные экземпляра, может сделать его понятным (или более понятным), что вы не хотите, чтобы кто-то не возился с вашими переменными. Однако вы не хотите, чтобы этот ганк на ваших публичных функциях. Это позволяет вам сделать это.
Он также может быть полезен, если вам нужно будет поддерживать старый интерфейс с одним набором имен одновременно с новым набором API с новым набором имен (SetLastname vs. Setsonname).
Старый пост, но я считаю важным отметить, что доступ к переменным рекомендуется осуществлять через геттеры и сеттеры (то есть с помощью точечной записи).Доступ к полю напрямую (_ivar) настоятельно рекомендуется только при его инициализации.
Есть хорошая статья Apple:https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatedData/EncapsulatedData.html
Последний абзац:
Вы всегда должны обращаться к переменным экземпляра непосредственно изнутри initialization, потому что в момент установки свойства Остальная часть объекта может быть еще не полностью инициализирована.Даже если вы не предоставляйте пользовательские методы доступа и не знайте о каких-либо побочных эффектах от В вашем собственном классе будущий подкласс вполне может переопределить поведение.