Objective-C 2.0のプロパティでは、対応するインスタンス変数を宣言する必要がありますか?たとえば、私はこのようなことをするのに慣れています:
MyObject.h
@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end
MyObject.m
@implementation
@synthesize name;
@end
ただし、代わりにこれを実行した場合:
MyObject.h
@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end
これはまだ有効ですか?そして、それは私の前の例とどのような違いがありますか?
Modern Objective-Cランタイム(iOS 3.x以上、または64ビットSnow Leopard以上)を使用している場合は、notこのような場合には、プロパティのivarを定義する必要があります。
@synthesize
プロパティ、ivarは実際に合成されます。これは、「fragile-ivar」シナリオを回避します。詳細については、 Cocoa with Love をご覧ください。
インターフェースでは、ブレースの間でインスタンス変数を正式に宣言するか、ブレースの外側の_@property
_を介して、またはその両方で宣言できます。いずれにしても、それらはクラスの属性になります。違いは、_@property
_を宣言すると、_@synthesize
_を使用して実装でき、ゲッター/セッターを自動コーディングできることです。自動コーダーのセッターは、整数を初期化し、たとえばゼロに浮動します。インスタンス変数を宣言し、対応する_@property
_を指定しない場合、_@synthesize
_およびmustを使用して独自のゲッター/セッターを作成することはできません。
独自に指定することにより、自動コード化されたゲッター/セッターをいつでもオーバーライドできます。これは通常、遅延ロードされるmanagedObjectContext
プロパティで行われます。したがって、managedObjectContext
をプロパティとして宣言するだけでなく、-(NSManagedObjectContext *)managedObjectContext
メソッドも記述します。インスタンス変数/プロパティと同じ名前のメソッドが「getter」メソッドであることを思い出してください。
_@property
_宣言メソッドでは、retain
やreadonly
などの他のオプションも使用できますが、これらはインスタンス変数宣言メソッドでは使用できません。基本的に、ivar
は古い方法であり、_@property
_はそれを拡張し、より面白く/簡単にします。自己を使用して参照できます。名前がそのクラスに固有である限り、プレフィックスかどうかは関係ありません。それ以外の場合、スーパークラスがあなたと同じプロパティ名を持っているなら、話している名前を指定するためにself.nameまたはsuper.nameのように言わなければなりません。
したがって、中括弧の間にivar
sを宣言する人が少なくなり、代わりに_@property
_を指定してから_@synthesize
_を実行するようになります。対応する_@synthesize
_なしでは、実装で_@property
_を実行できません。 Synthesizerは、_@property
_仕様から属性のタイプのみを認識します。合成ステートメントでは、プロパティの名前を変更することもできます。これにより、コード内で1つの名前(略記)でプロパティを参照できますが、.hファイルでは外部でフルネームを使用できます。ただし、XCodeにある非常にクールなオートコンプリートでは、これはあまり利点ではありませんが、まだあります。
これが、あちこちに浮かんでいるすべての混乱と誤報を解消するのに役立つことを願っています。
両方の方法で動作しますが、中括弧で宣言しないと、デバッガーでxcodeの値が表示されません。
XCode 4.4以降を使用している場合、コードを合成するインスタンス変数が生成されます。
以下のようなプロパティを宣言するだけです。合成コードとインスタンス変数宣言コードを生成します。
@property (nonatomic, strong) NSString *name;
合成コードを生成します
@synthesize name = _name;
_nameを使用してインスタンス変数にアクセスできます。
NSString* _name
しかし、読み取り専用プロパティを宣言すると、次のようになります
@property (nonatomic, strong, readonly) NSString *name;
コードを生成します
@synthesize name;
または
@synthesize name = name;
したがって、独自の合成コードを記述できる方法であれば、接頭辞「_」を付けてインスタント変数名にアクセスする必要があります。そうすると、コンパイラーがコードを生成します。あなたは書ける
@synthesize name = _name;
ドキュメントから:
一般に、プロパティの動作は最新のランタイムとレガシーランタイムの両方で同じです(Objective-Cランタイムプログラミングガイドの「ランタイムバージョンとプラットフォーム」を参照)。重要な違いが1つあります。最新のランタイムはインスタンス変数合成をサポートしますが、レガシーランタイムはサポートしません。
レガシーランタイムで@synthesizeを機能させるには、同じ名前で互換性のあるプロパティのインスタンス変数を指定するか、@ synthesizeステートメントで別の既存のインスタンス変数を指定する必要があります。最新のランタイムでは、インスタンス変数を提供しない場合、コンパイラがインスタンス変数を追加します。
Objective-Cプログラミング言語:プロパティ実装ディレクティブ
ランタイムに依存するアクセサ合成の動作には違いがあります(「ランタイムの違い」も参照)。
レガシーランタイムの場合、インスタンス変数は、現在のクラスの@interfaceブロックで既に宣言されている必要があります。プロパティと同じ名前のインスタンス変数が存在し、その型がプロパティの型と互換性がある場合、その変数が使用されます。そうでない場合は、コンパイラエラーが発生します。
最新のランタイム(Objective-Cランタイムプログラミングガイドの「ランタイムバージョンとプラットフォーム」を参照)の場合、インスタンス変数は必要に応じて合成されます。同じ名前のインスタンス変数が既に存在する場合は、それが使用されます。