Как работает подчеркивание перед переменной в классе target-c какао? - PullRequest
156 голосов
/ 05 мая 2009

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

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

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

@property (nonatomic, retain) UILabel *missionName;

- (Mission *)mission;

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

aMission.missionName = missionName;

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

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

Ответы [ 9 ]

96 голосов
/ 05 мая 2009

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

@synthesize missionName = _missionName;

В общем, это:

@synthesize propertyName = _ivarName;
18 голосов
/ 05 мая 2009

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

9 голосов
/ 16 июня 2011

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

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

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

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

5 голосов
/ 05 мая 2009

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

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

2 голосов
/ 05 июля 2013

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

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

1 голос
/ 29 января 2013

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

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

Ray

1 голос
/ 19 апреля 2012

Подчеркивание не только позволяет разрешать ваши ивары, не прибегая к использованию синтаксиса 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];
    }
}
0 голосов
/ 29 сентября 2015

В других ответах отсутствует то, что использование _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 голосов
/ 24 апреля 2015

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...