ヘッダーファイルで変数を2回定義する必要があるのはなぜですか?これらの変数にはどのような違いがありますか?
最初の定義はここにあります:
@interface MyController: UIViewController
{
NSInteger selectedIndex;
}
2番目の定義はここにあります:
@property (nonatomic) NSInteger selectedIndex;
ヘッダーファイルで変数を2回定義する必要があるのはなぜですか?これらの変数にはどのような違いがありますか?
最初の定義はここにあります:
@interface MyController: UIViewController
{
NSInteger selectedIndex;
}
2番目の定義はここにあります:
@property (nonatomic) NSInteger selectedIndex;
表示されているものは、Objective-Cの以前のバージョンでは必要でしたが、現在はそうではありません。
新しいランタイムが導入されるまで(Mac OSXのObjective-C2.0で)NeXTで使用されていたObjective-Cの最初のバージョンでは、すべてのインスタンス変数をクラスの構造の一部として宣言する必要がありました
@interface
。その理由は、クラスをサブクラス化した場合、コンパイラーは、サブクラスのインスタンス変数を配置するオフセットを確認できるように、クラスのインスタンス変数のレイアウトを知る必要があるためです。プロパティが導入されたとき、合成されたプロパティは、クラスの構造内のインスタンス変数によって「バックアップ」される必要がありました。したがって、インスタンス変数とプロパティの両方を宣言する必要がありました。
上記のすべてはもはや真実ではありません。新しいObjective-Cは、インスタンス変数のオフセットを検索する方法が脆弱ではありません。これは、いくつかの変更を意味します。
- すべてのインスタンス変数がにある必要はありません
@interface
。@implementation
衝突やその他の問題が発生する可能性があるため、カテゴリではなく、:で定義できるようになりました。- 合成されたプロパティのインスタンス変数は、プロパティ定義に基づいて推測および作成できます。
- 実行時に作成するクラスにインスタンス変数をプログラムで追加できます(システムで使用可能なクラスを登録する前のみ)。
したがって、繰り返しになりますが、Objective-C言語の古いバージョンでは、インスタンス変数と合成プロパティの両方を宣言するだけで済みます。あなたが見ているものは冗長であり、「ベストプラクティス」と見なされるべきではありません。
他の人が指摘しているように、ヘッダーで合成プロパティのバッキングインスタンス変数を宣言する必要はなくなりました。
To make this a bit clearer though: What you're seeing are not two declarations of the same variable, it is one declaration of the variable and one declaration of the property.
A property is basically a set of methods (in this case selectedIndex
and setSelectedIndex:
) that are typically used to access instance variables. There is a difference between a property and an instance variable. The property's setter/getter could do more than just set the variable, in your example, it could also e.g. update the UI to reflect the change of the selected index or the getter could infer the index from some other variable (in this case, there might be a selection index path), etc.
プロパティを合成すると、これらのメソッドを自分で実装する必要がなくなり、変数を設定するだけのデフォルトの実装が提供されますが、他のメソッドと同じようselectedIndex
にsetSelectedIndex:
自分で実装することもできます。その場合、インスタンス変数自体が必要になるか、完全に省略されます。 (推定プロパティの場合)。
最新のランタイムでは、それらを2回宣言する必要はありません。使用するだけです:
あなたの中で.h
@property (nonatomic) NSInteger selectedIndex;
{}の間の部分は、iVarの宣言です。そして、@ propertyを使用して、getterとsetterを宣言します。最近のランタイムでは、上記のコードを使用する場合、基本的に同じと言います(iVarは_selectedIndexになります)。