@property
を呼び出すときに、Objective-Cでアンダースコアを使用することとself
キーワードを使用することの違いはありますか?
プロパティ宣言:
@property (weak, nonatomic) NSString *myString;
プロパティで@synthesize
を呼び出す:
@synthesize myString = _myString;
コードで使用する場合、違いはありますか?いつ?ゲッター/セッターで?
self.myString = @"test";
_myString = @"test";
self.myString = @"test";
は、[self setMyString:@"test"];
とまったく同じです。これらは両方ともメソッドを呼び出しています。
このメソッドを自分で作成することもできます。次のようになります。
- (void)setMyString:(NSString*)newString
{
_myString = newString;
}
@synthesize
を使用したので、実際にそのメソッドを記述する必要はありません。コンパイラーがそれを記述できるようにするだけです。
ですから、そのメソッドを見ると、それを呼び出すことは、インスタンス変数に値を割り当てることとまったく同じことをするように見えますよね?まあ、それはそれほど単純ではありません。
まず、独自のセッターメソッドを作成できます。そうすると、メソッドが呼び出され、変数を設定するだけでなく、あらゆる種類の追加処理を実行できます。その場合、self.myString =
を使用するとメソッドが呼び出されますが、_myString =
を実行すると呼び出されないため、異なる機能が使用されます。
次に、Key Value Observingを使用する場合、コンパイラは非常に巧妙なトリックを実行します。背後で、Key Value Observingが機能するために必要なwillChangeValueForKey:
の呼び出しを行うために、クラスをサブクラス化し、セッターメソッドをオーバーライドします(自分で作成したものでも、シンセシスで生成されたものでも)。これがどのように機能するかを知る必要はありません(ただし、就寝前の読書が必要な場合は非常に興味深いです!)が、Key Value Observingが自動的に機能するようにしたい場合は、セッターメソッドを使用する必要があることを知っておく必要があります。
第三に、シンセに依存して書き込みを行う場合でもセッターメソッドを呼び出すと、将来の柔軟性が得られます。値が変更されるたびに何か特別なことをしたいと思うかもしれません。そして、それをしたいことに気付いた時点で、セッターメソッドを手動で書くことができます—常にself.myString =
を使用する習慣があるなら、新しいメソッドの呼び出しを開始するには、残りのコードを変更する必要があります!
第4に、サブクラスにも同じことが当てはまります。他の誰かがコードをサブクラス化する場合、セッターを使用すると、セッターはそれらをオーバーライドして機能を調整できます。
インスタンス変数に直接アクセスするときはいつでも、その時点で追加機能をフックする方法を明示的に提供していません。あなたや他の誰かが将来そのような機能をフックしたいと思うかもしれないので、そうしない正当な理由がない限り、セッターを常に使用することは有益です。
あなたは正しい-最初のバージョン(self.myString
)合成されたゲッター/セッターを呼び出し、2番目のバージョンはプライベートメンバー変数に直接アクセスします。
ARCを使用しているように見えるので、その場合、それほど大きな違いはありません。ただし、ARCを使用していない場合、プライベートメンバーに直接割り当てても、synthesize
を使用して生成される自動保持/解放またはコピー/解放ロジックがトリガーされないため、違いが生じる可能性があります。
_
(アンダースコア)は、 この質問 で説明されているように、単なる規則です。
プロパティアクセスの前にself.
を付けない場合、c struct
のように、基になる変数に直接アクセスします。一般的に、initメソッドおよびカスタムプロパティアクセサーでのみこれを行う必要があります。これにより、計算されたプロパティや [〜#〜] kvc [〜#〜] などが意図したとおりに機能します。
言及されていないヒントがあります。アンダースコアを使用したアクセスはより高速で、自己を使用したアクセスはより安全です(KVC)。たぶん、これを使用する必要があるときに要約できます。