web-dev-qa-db-ja.com

Cocoa Objective-Cクラスの変数の前にあるアンダースコアはどのように機能しますか?

いくつかのiPhoneの例で、属性が変数の前にアンダースコア_を使用しているのを見てきました。誰もがこれが何を意味するか知っていますか?またはそれがどのように機能しますか?

私が使用しているインターフェイスファイルは次のようになります。

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

@property (nonatomic, retain) UILabel *missionName;

- (Mission *)mission;

上記が何をするのか正確にはわかりませんが、ミッション名を次のように設定しようとすると:

aMission.missionName = missionName;

エラーが表示されます:

構造体または共用体ではない何かのメンバー 'missionName'の要求

156
Atma

Ivarにアンダースコアプレフィックスを使用する場合(これは一般的な規則にすぎませんが、便利なものです)、自動生成されたアクセサー(プロパティ用)が使用するivarを認識できるように、余分なことを1つ行う必要があります。具体的には、実装ファイルでは、synthesizeは次のようになります。

@synthesize missionName = _missionName;

より一般的には、これは次のとおりです。

@synthesize propertyName = _ivarName;
96
Kelan

これは読みやすさのための単なる慣習であり、コンパイラにとって特別なことは何もしません。プライベートインスタンス変数とメソッド名で使用されることがわかります。 Appleは実際にアンダースコアを使用しないことをお勧めします(注意を払っていない場合はスーパークラスで何かをオーバーライドできます)が、そのアドバイスを無視することを気にしないでください。)

18

私が見た唯一の有用な目的は、上記のようにローカル変数とメンバー変数を区別することですが、これは必須の規則ではありません。 @propertyと組み合わせると、合成ステートメントの冗長性が向上します– @synthesize missionName = _missionName;、およびどこでもいです。

アンダースコアを使用する代わりに、競合しないメソッド内で説明的な変数名を使用してください。競合する必要がある場合は、メソッド内の変数名には、複数のメソッドで使用される可能性のあるメンバー変数ではなく、アンダースコアが必要です。これが有用な唯一の一般的な場所は、setterまたはinitメソッドです。さらに、@ synthesizeステートメントをより簡潔にします。

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

編集:自動合成の最新のコンパイラー機能により、ivarにアンダースコアを使用するようになりました(まれに、自動合成の機能に合わせてivarを使用する必要がある場合があります)。

9
Peter DeWeese

これは実際には何の意味もありません。メンバー変数とローカル変数を区別するために使用する規則です。

エラーについては、aMissionのタイプが間違っているようです。その宣言は何ですか?

5
smorgan

これは、合成プロパティの命名規則専用です。

.mファイルで変数を合成すると、Xcodeは_variable Intelligenceを自動的に提供します。

2
Dipak Narigara

アンダースコアを使用すると、self.member構文を使用せずにivarを解決できるだけでなく、変数が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];
    }
}
1

これは、self.variableName対_variablenameに関する質問の「マスター」項目のようです。ループのために私を投げたのは、.hで、私が持っていたことでした:

...
@interface myClass : parentClass {
className *variableName;    // Note lack of _
}

@property (strong, nonatomic) className  *variableName;
...

これにより、self.variableNameと_variableNameが.mの2つの異なる変数になります。私が必要としていたのは:

...
@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 nameを使用するか、変数を合成してアンダースコアなしで変数またはアウトレットを使用できます。

0
SARATH SASI