いくつかのiPhoneの例で、属性が変数の前にアンダースコア_を使用しているのを見てきました。誰もがこれが何を意味するか知っていますか?またはそれがどのように機能しますか?
私が使用しているインターフェイスファイルは次のようになります。
@interface MissionCell : UITableViewCell {
Mission *_mission;
UILabel *_missionName;
}
@property (nonatomic, retain) UILabel *missionName;
- (Mission *)mission;
上記が何をするのか正確にはわかりませんが、ミッション名を次のように設定しようとすると:
aMission.missionName = missionName;
エラーが表示されます:
構造体または共用体ではない何かのメンバー 'missionName'の要求
Ivarにアンダースコアプレフィックスを使用する場合(これは一般的な規則にすぎませんが、便利なものです)、自動生成されたアクセサー(プロパティ用)が使用するivarを認識できるように、余分なことを1つ行う必要があります。具体的には、実装ファイルでは、synthesize
は次のようになります。
@synthesize missionName = _missionName;
より一般的には、これは次のとおりです。
@synthesize propertyName = _ivarName;
これは読みやすさのための単なる慣習であり、コンパイラにとって特別なことは何もしません。プライベートインスタンス変数とメソッド名で使用されることがわかります。 Appleは実際にアンダースコアを使用しないことをお勧めします(注意を払っていない場合はスーパークラスで何かをオーバーライドできます)が、そのアドバイスを無視することを気にしないでください。)
私が見た唯一の有用な目的は、上記のようにローカル変数とメンバー変数を区別することですが、これは必須の規則ではありません。 @propertyと組み合わせると、合成ステートメントの冗長性が向上します– @synthesize missionName = _missionName;
、およびどこでもいです。
アンダースコアを使用する代わりに、競合しないメソッド内で説明的な変数名を使用してください。競合する必要がある場合は、メソッド内の変数名には、複数のメソッドで使用される可能性のあるメンバー変数ではなく、アンダースコアが必要です。これが有用な唯一の一般的な場所は、setterまたはinitメソッドです。さらに、@ synthesizeステートメントをより簡潔にします。
-(void)setMyString:(NSString*)_myString
{
myString = _myString;
}
編集:自動合成の最新のコンパイラー機能により、ivarにアンダースコアを使用するようになりました(まれに、自動合成の機能に合わせてivarを使用する必要がある場合があります)。
これは実際には何の意味もありません。メンバー変数とローカル変数を区別するために使用する規則です。
エラーについては、aMissionのタイプが間違っているようです。その宣言は何ですか?
これは、合成プロパティの命名規則専用です。
.mファイルで変数を合成すると、Xcodeは_variable Intelligenceを自動的に提供します。
アンダースコアを使用すると、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];
}
}
これは、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は同等です。
私がまだ明確になっていないのは、なぜ多くの例がまだ機能するのか、それが難しいとしてもです。
レイ
他の答えに欠けているのは、_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;
}
アンダースコアの代わりにself.variable nameを使用するか、変数を合成してアンダースコアなしで変数またはアウトレットを使用できます。