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

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

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

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

@property (nonatomic, retain) UILabel *missionName;

- (Mission *)mission;

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

aMission.missionName = missionName;

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

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

Ответ 1

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

@synthesize missionName = _missionName;

В общем, это:

@synthesize propertyName = _ivarName;

Ответ 2

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

Ответ 3

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

Кажется, это "главный" элемент для вопросов о self.variableName vs. _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 эквивалентны.

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

Луч

Ответ 8

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

Ответ 9

Отсутствие других ответов заключается в том, что использование _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;

}