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

StackOverflow https://stackoverflow.com/questions/822487

Вопрос

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

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

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

@property (nonatomic, retain) UILabel *missionName;

- (Mission *)mission;

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

aMission.missionName = missionName;

Я получаю сообщение об ошибке:

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

Это было полезно?

Решение

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

@synthesize missionName = _missionName;

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

@synthesize propertyName = _ivarName;

Другие советы

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

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

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

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

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

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

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

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

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

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

Пример:

- (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 против_ переменное имя.Что сбило меня с толку, так это то, что в .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 и получать доступ к 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;

}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top