@synthesizeは正確には何をしますか?


148

次のコードを確認しました。

//example.h
MKMapView * mapView1;
@property (nonatomic, retain) MKMapView * mapView;

//example.m
@synthesize mapView = mapView1

関係は何であるmapViewとはmapView1?それはsetgetメソッドを作成しmapView1ますか?


1
更新:しかし、最新のツールセットでは、@ synthesizeが(ほとんど)不要になりました。その他のスタックオーバーフローに関する質問への回答をご覧ください。
Ali Beadle 2013年

回答:


228

あなたの例では、mapView1あるインスタンス変数(IVAR)で定義されたクラスのインスタンスに属するメモリストレージの部分example.hexample.mプロパティmapViewの名前です。プロパティは、ドット表記を使用して読み取りまたは設定できるオブジェクトの属性です。プロパティはivarに基づく必要はありません、ほとんどのプロパティはそれに基づいています。宣言は、単にと呼ばれるプロパティがあることを世界に伝えます。myObject.mapView@propertymapView

@synthesize mapView = mapView1;

この行は、にsetterとgetterを作成するようコンパイラーに指示しmapView、と呼ばれるivarを使用するように指示しますmapView1。この= mapView1部分がないと、コンパイラーは、プロパティーとivarが同じ名前であると想定します。(この場合、と呼ばれるivarがないため、コンパイラエラーが発生しますmapView。)

この@synthesizeステートメントの結果は、このコードを自分で追加した場合と同様です。

-(MKMapView *)mapView
{
   return mapView1;
}

-(void)setMapView:(MKMapView *)newMapView
{
  if (newMapView != mapView1)
  {
    [mapView1 release];
    mapView1 = [newMapView retain];
  }
}

そのコードを自分でクラスに追加した場合、@synthesizeステートメントを次のように置き換えることができます。

@dynamic mapView;

主なことは、ivarとプロパティの概念を明確に区別することです。それらは実際には2つの非常に異なる概念です。


31

@synthesize 変数のゲッターとセッターを作成します。

これにより、変数にいくつかの属性を指定でき@synthesize、そのプロパティを変数に設定すると、変数のゲッターとセッターが生成されます。

プロパティ名は変数名と同じにすることができます。時々 、人々はそれを使用するように、それは異なるものにしたいinitか、deallocまたはパラメータは、同じ変数の名前で渡されたとき。


16

ドキュメントから:

@synthesizeキーワードを使用して、@ implementationブロック内でこれらのメソッドを指定しない場合は、プロパティのセッターメソッドやゲッターメソッドを合成するようコンパイラーに指示します。


8

レガシーコードを編集するときにこの問題に遭遇したので、知っておく必要がある既存の回答に追加のメモを作りたいと思います。

新しいコンパイラバージョンでも、省略した@synthesize propertyNameかどうかによって違いが生じる場合があります

次のように、インスタンス変数合成しながら、アンダースコアなしでインスタンス変数を宣言する場合:

ヘッダ:

@interface SomeClass : NSObject {
   int someInt;
}
@property int someInt;
@end

実装:

@implementation SomeClass
@synthesize someInt;
@end

self.someIntと同じ変数にアクセスしますsomeInt。ivarsの先頭のアンダースコアを使用しないと、命名規則に従いませんが、そのようなコードを読んで変更しなければならない状況になりました。

しかし、「ねえ、@ synthesizeはもう新しいコンパイラを使用しているので、もう重要ではない」と思ったら、間違いです!次に、クラスは2つのivar、つまりsomeInt、自動生成された_someInt変数を持つことになります。このようにself.someIntしてsomeInt、それ以上同じ変数に対処しません。私のようにそのような行動を期待していない場合、これはあなたにいくつかの頭痛を見つけるかもしれません。


"同期"!= "合成"?
jameshfisher 2015年

はい、これらは2つの異なる概念です。@synchronizeプロパティにアクセスするときにスレッドを同期する方法のディレクティブであり、@synthesizeゲッターとセッターを介してプロパティをインスタンス変数にバインドするためのものです。
Lars Blumberg

1
jameshfisherのコメントは、同期と合成を混乱させていることを警告するためのものです。この2つは同じ意味で使用します。
メイプル

1
それを知らせてくれてありがとう!私はそれを完全に監督し、存在しない@synchronizeキーワードを使用しないように答えを更新しました。
Lars Blumberg 2016年

その場合、xcode 10は問題について警告しますAutosynthesized property 'someInt' will use synthesized instance variable '_someInt', not existing instance variable 'someInt'。(私はこの警告が追加されたxcodeのバージョンを知りません。)
zwcloud 2018年

7

アップルのドキュメントのとおり、@ Synthesizeはインスタンス変数の名前を変更するためにのみ使用されます。例えば

@property NSString *str;

@synthesize str = str2; 

さて_str、上記の行はインスタンス変数の名前をstr2

@property オブジェクトを他のクラスのオブジェクトで使用できるようにします。つまり、オブジェクトをパブリックにします。


3
明らかに、Xcode 4.4以降、Clangは宣言されたプロパティの自動合成をサポートしています。そのため、ほとんどの場合、@ synthesizeは不要です。useyourloaf.com/blog/2012/08/01/…を
huyz

5

@interfaceでプロパティを作成すると、そのプロパティは_propertyNameという名前のインスタンス変数によって自動的に戻されます。そのため、firstNameという名前のプロパティを作成すると、舞台裏コンパイラはデフォルトで_firstNameという名前のインスタンス変数を作成します。コンパイラーは、あなたのためにゲッターとセッターのメソッドも作成します(つまり、firstName、setFirstName)。

これで、プロパティを@synthesize firstNameで合成するとき、コンパイラーにインスタンス変数(_firstName)の名前をfirstNameに変更するように指示するだけです。バックアップされたインスタンス変数の名前を別の名前に変更する場合は、プロパティ名を合成するときに別の名前を割り当てるだけです(つまり、@ synthesize firstName = myFirstName)。これを行うと、myFirstnameという名前のインスタンス変数によってプロパティがバックアップされます。

つまり、要するに、ほとんどの場合、@ synthesizeは、プロパティによってバックアップされたインスタンス変数の名前を変更するために使用されていました。



2

オブジェクトのゲッターとセッターを作成します。あなたはこのようなものでアクセスできます:

MKMapView* m = object.mapView;

または

object.mapView = someMapViewObject

mapView1はクラス内のivarの名前、mapViewはゲッター/セッターメソッドの名前です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.