Как работает подчеркивание перед переменной в классе target-c какао?
Я видел в нескольких примерах iPhone, что атрибуты используют подчеркивание _ перед переменной. Кто-нибудь знает что это значит? Или как это работает?
Файл интерфейса, который я использую, выглядит следующим образом:
@interface MissionCell : UITableViewCell {
Mission *_mission;
UILabel *_missionName;
}
@property (nonatomic, retain) UILabel *missionName;
- (Mission *)mission;
Я не уверен точно, что делает вышеупомянутое, но когда я пытаюсь установить название миссии как:
aMission.missionName = missionName;
Я получаю ошибку:
запрос на членство 'missionName' в чем-то, что не является структурой или объединением
9 ответов
Если вы используете префикс подчеркивания для своего ivars (который является не чем иным, как обычным соглашением, но полезным), то вам нужно сделать 1 дополнительную вещь, чтобы автоматически сгенерированный аксессор (для свойства) знал, какой ivar использовать. В частности, в вашем файле реализации, ваш synthesize
должен выглядеть так:
@synthesize missionName = _missionName;
В более общем смысле это:
@synthesize propertyName = _ivarName;
Это просто соглашение по удобочитаемости, оно не делает ничего особенного для компилятора. Вы увидите, как люди используют его для личных переменных экземпляра и имен методов. Apple фактически рекомендует не использовать подчеркивание (если вы не будете осторожны, вы можете переопределить что-то в своем суперклассе), но вы не должны расстраиваться из-за игнорирования этого совета.:)
Единственная полезная цель, которую я видел, состоит в том, чтобы различать локальные переменные и переменные-члены, как указано выше, но это не является необходимым соглашением. В сочетании с @property, это увеличивает многословность операторов синтеза - @synthesize missionName = _missionName;
и везде безобразно.
Вместо использования подчеркивания, просто используйте описательные имена переменных внутри методов, которые не конфликтуют. Когда они должны конфликтовать, имя переменной в методе должно иметь подчеркивание, а не переменную-член, которая может использоваться несколькими методами. Единственное общее место, где это полезно, находится в установщике или в методе init. Кроме того, это сделает оператор @synthesize более лаконичным.
-(void)setMyString:(NSString*)_myString
{
myString = _myString;
}
Редактировать: с последней функцией компиляции автосинтеза, я теперь использую подчеркивание для ивара (в редких случаях, когда мне нужно использовать ивар, чтобы соответствовать тому, что делает автосинтез.
На самом деле это ничего не значит, это просто соглашение, которое некоторые люди используют для дифференциации переменных-членов от локальных переменных.
Что касается ошибки, похоже, что aMission имеет неправильный тип. Каково это его объявление?
Это только для соглашения об именовании свойств синтеза.
Когда вы синтезируете переменные в файле.m, Xcode автоматически предоставит вам _variable интеллект.
Наличие подчеркивания не только позволяет разрешать ваши ивары, не прибегая к использованию синтаксиса self.member, но и делает ваш код более читабельным, поскольку вы знаете, когда переменная является иваром (из-за префикса подчеркивания) или аргументом-членом (без подчеркивания)).
Пример:
- (void) displayImage: (UIImage *) image {
if (image != nil) {
// Display the passed image...
[_imageView setImage: image];
} else {
// fall back on the default image...
[_imageView setImage: _image];
}
}
Похоже, что это "главный" пункт для вопросов о self.variableName и _variablename. Что бросило меня в тупик, так это то, что в.h у меня было:
...
@interface myClass : parentClass {
className *variableName; // Note lack of _
}
@property (strong, nonatomic) className *variableName;
...
Это приводит к тому, что self.variableName и _variableName являются двумя различными переменными в.m. Что мне нужно было:
...
@interface myClass : parentClass {
className *_variableName; // Note presence of _
}
@property (strong, nonatomic) className *variableName;
...
Затем в классе '.m self.variableName и _variableName эквивалентны.
Что я до сих пор не понимаю, так это то, почему многие примеры все еще работают, даже если это не сделано.
луч
Вместо подчеркивания вы можете использовать имя self.variable или вы можете синтезировать переменную, чтобы использовать переменную или выход без подчеркивания.
Из других ответов отсутствует то, что с помощью _variable
мешает вам рассеянно печатать variable
и доступ к ивуру, а не (предположительно предполагаемому) свойству.
Компилятор заставит вас использовать либо self.variable
или же _variable
, Использование подчеркивания делает невозможным ввод текста variable
, что уменьшает ошибки программиста.
- (void)fooMethod {
// ERROR - "Use of undeclared identifier 'foo', did you mean '_foo'?"
foo = @1;
// So instead you must specifically choose to use the property or the ivar:
// Property
self.foo = @1;
// Ivar
_foo = @1;
}