web-dev-qa-db-ja.com

Objective-Cのivarとプロパティの違いは何ですか

Objective-Cでivarとプロパティを使用するこれら3つの方法のセマンティックの違いは何ですか?

1。

@class MyOtherObject; 
@interface MyObject {
}
@property (nonatomic, retain) MyOtherObject *otherObj;

2。

#import "MyOtherObject.h"
@interface MyObject {
    MyOtherObject *otherObj;
}
@property (nonatomic, retain) MyOtherObject *otherObj;

3。

#import "MyOtherObject.h"
@interface MyObject {
    MyOtherObject *otherObj;
}
80
ennuikiller

Number 1 MyOtherObjectクラスを前方宣言することで他の2つとは異なり、コンパイラーとリンカーが見るコードの量を最小限に抑え、循環参照を潜在的に回避します。この方法で行う場合は、#importを.mファイルに入れることを忘れないでください。

@property(および.mの@synthesizeに一致する)ファイルを宣言することにより、指定した方法で処理されたメモリセマンティクスでアクセサメソッドを自動生成します。ほとんどのオブジェクトの経験則は保持ですが、たとえばNSStringsはコピーを使用する必要があります。一方、シングルトンとデリゲートは通常、Assignを使用する必要があります。手書きのアクセサーは退屈でエラーが発生しやすいため、これにより多くのタイピングや愚かなバグを節約できます。

また、合成されたプロパティを宣言すると、次のようなドット表記を使用してアクセサメソッドを呼び出すことができます。

self.otherObj = someOtherNewObject; // set it  
MyOtherObject *thingee = self.otherObj; // get it 

通常のメッセージ受け渡し方法の代わりに:

[self setOtherObject:someOtherNewObject]; // set it
MyOtherObject *thingee = [self otherObj]; // get it 

舞台裏では、次のようなメソッドを実際に呼び出しています。

- (void) setOtherObj:(MyOtherObject *)anOtherObject {

    if (otherObject == anOtherObject) {
        return;  
    }

    MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second
    otherObject = [anOtherObject retain]; // put the new value in  
    [oldOtherObject release]; // let go of the old object
} // set it

…またはこれ

- (MyOtherObject *) otherObject {  
    return otherObject;
} // get it

お尻の完全な痛み、右。これをクラスのevery ivarに対して行います。正しく実行しないと、メモリリークが発生します。コンパイラーに作業を任せるのが最善です。

Number 1にはivarがないことがわかります。それがタイプミスではないと仮定すれば、@ property/@synthesizeディレクティブが舞台裏であなたのためにivarを宣言するので問題ありません。 これはMac OS X-Snow LeopardとiOS4の新機能だと思います。

Numberにはこれらのアクセサーが生成されていないため、自分で記述する必要があります。アクセサメソッドに副作用を持たせたい場合は、上記のように標準のメモリ管理ダンスを行い、その後、アクセサメソッド内で必要なサイドワークを実行します。プロパティを合成する場合同様に独自のコードを書くの場合、yourバージョンが優先されます。

すべてをカバーしましたか?

56
willc2

昔はivarがあり、他のクラスを設定または読み取りたい場合は、ゲッター(つまり-(NSString *)foo)とセッター(つまり-(void)setFoo:(NSString *)aFoo;)を定義する必要がありました)。

プロパティが提供するのは、セッターとゲッターを無料で(ほぼ!)ivarと共に使用することです。そのため、プロパティを今定義するとき、原子性を設定することができます(たとえば、複数のスレッドからの複数の設定アクションを許可しますか)、およびセマンティクスの割り当て/保持/コピー(つまり、セッターが新しい値をコピーする必要があります)または単に現在の値を保存します-別のクラスが後で変更される可能性のある可変文字列で文字列プロパティを設定しようとしている場合に重要です)。

これは@synthesizeが行うことです。多くの人はivar名を同じままにしますが、合成ステートメントを記述するときに変更できます(つまり、@synthesize foo=_foo;は、プロパティfooに対して_fooという名前のivarを作成することを意味します。このプロパティの読み取りまたは書き込みを行い、self.fooを使用しない場合は、_foo = ...を使用する必要があります。セッターのみを使用する場合は、ivarへの直接参照をキャッチするのに役立ちます。ゲッター)。

Xcode 4.6では、@synthesizeステートメントを使用する必要はありません-コンパイラーが自動的に実行し、デフォルトでivarの名前の前に_を追加します。

16
David H