it-swarm.com.ru

Как работает подчеркивание перед переменной в классе target-c какао?

Я видел в нескольких примерах iPhone, что атрибуты используют подчеркивание _ перед переменной. Кто-нибудь знает что это значит? Или как это работает?

Файл интерфейса, который я использую, выглядит следующим образом:

@interface MissionCell : UITableViewCell {
    Mission *_mission;
    UILabel *_missionName;
}

@property (nonatomic, retain) UILabel *missionName;

- (Mission *)mission;

Я не уверен точно, что делает вышеупомянутое, но когда я пытаюсь установить название миссии как:

aMission.missionName = missionName;

Я получаю ошибку:

запрос на членство 'missionName' в чем-то, не являющемся структурой или объединением

156
Atma

Если вы используете префикс подчеркивания для своих ivars (который является не чем иным, как обычным соглашением, но полезным), то вам нужно сделать 1 дополнительную вещь, чтобы автоматически сгенерированный аксессор (для свойства) знал, какой ivar использовать. В частности, в вашем файле реализации ваше synthesize должно выглядеть так:

@synthesize missionName = _missionName;

В более общем смысле это:

@synthesize propertyName = _ivarName;
96
Kelan

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

18
Marc Charbonneau

Единственная полезная цель, которую я видел, состоит в том, чтобы различать локальные переменные и переменные-члены, как указано выше, но это не является необходимым соглашением. В паре с @property это увеличивает многословность синтезирующих операторов - @synthesize missionName = _missionName;, и везде безобразно.

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

-(void)setMyString:(NSString*)_myString
{
    myString = _myString;
}

Edit: Благодаря последней функции компилятора автоматического синтеза я теперь использую подчеркивание для ivar (в редких случаях, когда мне нужно использовать ivar для соответствия функциям автоматического синтеза.

9
Peter DeWeese

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

Что касается ошибки, похоже, что aMission имеет неправильный тип. Каково это его объявление?

5
smorgan

Это только для соглашения об именовании свойств синтеза.

Когда вы синтезируете переменные в файле .m, XCode автоматически предоставит вам _variable интеллект.

2
Dipak Narigara

Наличие подчеркивания не только позволяет разрешать ваши ивары, не прибегая к использованию синтаксиса 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];
    }
}
1
Jason Fuerstenberg

Похоже, что это "главный" пункт для вопросов о 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 эквивалентны.

Что я до сих пор не понимаю, так это то, почему многие примеры все еще работают, даже если это не сделано.

Луч

1
RayInNoIL

Из других ответов отсутствует то, что использование _variable не позволяет вам бездумно набирать variable и получать доступ к ivar, а не к (предположительно предполагаемому) свойству.

Компилятор заставит вас использовать 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;

}
0
pkamb

вместо подчеркивания вы можете использовать имя self.variable или вы можете синтезировать переменную, чтобы использовать переменную или выход без подчеркивания.

0
SARATH SASI