102

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

これはまだ有効ですか?そして、それは私の前の例とは何か違うのですか?

4

6 に答える 6

93

最新のObjective-Cランタイム(iOS3.x以降または64ビットのSnowLeopard以降)を使用している場合、このような場合にプロパティにivarを定義する必要はありません。

あなた@synthesizeがプロパティを作成すると、ivarは事実上あなたのためにも合成されます。これは「壊れやすいivar」シナリオを回避します。あなたは愛をこめてココアでそれについてもっと読むことができます

于 2010-06-19T04:26:31.143 に答える
71

@propertyインターフェイスでは、中括弧の間、中括弧の外側、またはその両方を介してインスタンス変数を正式に宣言できます。いずれにせよ、それらはクラスの属性になります。違いは、を宣言する@propertyと、を使用して実装できること@synthesizeです。これにより、ゲッター/セッターが自動コーディングされます。たとえば、オートコーダーセッターは整数を初期化し、ゼロにフロートします。インスタンス変数を宣言し、対応するを指定し@propertyない場合は、を使用できず、独自のゲッター/セッターを作成する必要@synthesizeがあります。

独自に指定することで、自動コード化されたゲッター/セッターをいつでもオーバーライドできます。これは通常、managedObjectContext遅延ロードされるプロパティを使用して行われます。したがって、あなたはあなたをプロパティとして宣言しますmanagedObjectContextが、それからメソッドも書き-(NSManagedObjectContext *)managedObjectContextます。インスタンス変数/プロパティと同じ名前のメソッドが「getter」メソッドであることを思い出してください。

宣言メソッドでは、インスタンス変数宣言メソッドでは不可能な、やなどの@property他のオプションも使用できます。基本的に、これは古い方法であり、それを拡張して、より魅力的で簡単にします。自己を使ってどちらかを参照することができます。プレフィックスであろうとなかろうと、名前がそのクラスに固有である限り、問題ではありません。それ以外の場合、スーパークラスのプロパティの名前があなたと同じである場合は、話している名前を指定するために、self.nameまたはsuper.nameのように言う必要があります。 retainreadonlyivar@property

ivarしたがって、中括弧の間にsを宣言する人はますます少なくなり、代わりに@property、を指定してから実行する方向にシフトし@synthesizeます。@synthesize対応するがなければ、実装で行うことはできません@property。シンセサイザーは、仕様からどのタイプの属性であるかのみを認識します@property。合成ステートメントを使用すると、プロパティの名前を変更できるため、コード内では1つの名前(省略形)でプロパティを参照できますが、.hファイルの外部ではフルネームを使用します。ただし、XCodeが現在持っている本当にクールなオートコンプリートでは、これはあまり利点ではありませんが、それでも存在します。

これが、あちこちに浮かんでいるすべての混乱と誤った情報を取り除くのに役立つことを願っています。

于 2011-02-02T05:22:58.983 に答える
8

どちらの方法でも機能しますが、中括弧で宣言しないと、xcodeのデバッガーに値が表示されません。

于 2011-04-13T03:04:18.410 に答える
3

ドキュメントから:

一般に、プロパティの動作は、モダンランタイムとレガシーランタイムの両方で同じです(Objective-Cランタイムプログラミングガイドの「ランタイムバージョンとプラットフォーム」を参照)。重要な違いが1つあります。最新のランタイムはインスタンス変数の合成をサポートしていますが、レガシーランタイムはサポートしていません。

@synthesizeをレガシーランタイムで機能させるには、プロパティと同じ名前と互換性のあるタイプのインスタンス変数を指定するか、@synthesizeステートメントで別の既存のインスタンス変数を指定する必要があります。最新のランタイムでは、インスタンス変数を指定しない場合、コンパイラーがインスタンス変数を追加します。

于 2011-03-28T06:07:33.523 に答える
3

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;
于 2013-03-18T06:27:38.830 に答える
1

Objective-Cプログラミング言語:プロパティ実装ディレクティブ

ランタイムに依存するアクセサ合成の動作には違いがあります(「ランタイムの違い」も参照)。

  • レガシーランタイムの場合、インスタンス変数は現在のクラスの@interfaceブロックですでに宣言されている必要があります。プロパティと同じ名前のインスタンス変数が存在し、そのタイプがプロパティのタイプと互換性がある場合は、それが使用されます。そうでない場合は、コンパイラエラーが発生します。

  • 最新のランタイム(Objective-Cランタイムプログラミングガイドの「ランタイムバージョンとプラットフォーム」を参照)の場合、インスタンス変数は必要に応じて合成されます。同じ名前のインスタンス変数がすでに存在する場合は、それが使用されます。

于 2012-01-11T06:13:20.750 に答える