web-dev-qa-db-ja.com

Objective-Cの@propertyおよび@synthesize

私が遊んでいて、物事がどのように機能するかを理解している間に https://github.com/enormego/EGOTableViewPullRefresh 私は@propertyと@synthesizeの不思議を発見しました。ここに私が言及したコードがあります

EGORefreshTableHeaderView.h

@interface EGORefreshTableHeaderView : UIView {
    id _delegate;
    EGOPullRefreshState _state;

    UILabel *_lastUpdatedLabel;
    UILabel *_statusLabel;
    CALayer *_arrowImage;
    UIActivityIndicatorView *_activityView;
}

@property(nonatomic,assign) id <EGORefreshTableHeaderDelegate> delegate;

EGORefreshTableHeaderView.m

@synthesize delegate=_delegate;

私はこれを読みました http://developer.Apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html そして私が理解していることから、デリゲートである_delegate。 (私はこの理解でよろしいですか?)

しかし、なぜこれらの@synthesize =ディレクティブを使用して複雑にする必要があるのか​​、まだ理解できません。

19
sarunw

本当に複雑ですか?これは、アクセサを作成するようコンパイラーに指示するプロパティのバッキングに使用するivarを指定できるようにするための、ほんの少しの構文です。彼らがこれまたは同等のものを提供しなかった場合は、プロパティ名を常にivar名と一致させる必要がありますが、それを望まない理由もあります。

Ivarに別の名前を付ける必要がない場合は、ivar名を指定する必要はありません。実際、プロパティに対してivarを作成する必要はまったくありません...作成しない場合、コンパイラーが作成します。

pdate: 2013年半ば以降、LLVMはデフォルトでプロパティのアクセサーを合成するため、ほとんどの場合、@synthesizeを指定する必要はありません。引き続き使用する1つのケースは、コンパイラーが生成するインスタンス変数とは異なるインスタンス変数を使用してプロパティをバックアップする場合です。また、プロパティをサポートするivarのデフォルト名は、アンダースコアが前に付いたプロパティ名になります。したがって、OPの例のコードは、次の行を削除することで簡略化できます。

id _delegate;

そして:

@synthesize delegate=_delegate;

アンダースコアプレフィックスを使用することに対する以前のアドバイスは、コンパイラーの現在の方法およびデフォルトの動作と明確に一致しないため、削除しました。ただし、私が知る限り、メソッド名にアンダースコアの接頭辞を使用するのは依然として不適切な形式です。

また、少なくとも1人の人が私の応答の最初の行を「本当にどれほど複雑か」と解釈したことに気づきました。降順として。それが1人の印象だったといいのですが、私は確かに何も言い訳をするつもりはありませんでしたが、@synthesize xxx=_xxx;ディレクティブが物事を複雑にするというOPの主張を中心に私の応答を組み立てようとしていました。あなたが始めているとき吸収する多くがあります。うまくいけば、新しい「デフォルトで合成」動作が新規参入者の負担を軽減するでしょう。

30
Caleb

あなたは正しい、使用しています

@synthesize foobar=_foobar;

ほとんどの場合、少し無意味ですが、抽象的なレベルでは、他の変数の値を完全に返すことができます。のように...

@synthesize foobar=fluffybunny;

アクセサーを使用するたびにfluffybunnyの値を取得または設定できます.foobar

ただし、@synthesize複雑さ、書きたいですか

-(void)setFoobar:(id)aobject {
    [self willSetValueForKey:"foobar"];
    id old = foobar;
    foobar = [aobject retain];
    [old release];
    [self didSetValueForKey:"foobar"];
}

-(id)foobar {
    [self willAccessValueForKey:"foobar"];
    id obj = [self primitiveValueForKey:@"foobar"];
    [self didAccessValueForKey:"foobar"];    
    return obj;
}

または

@synthesize foobar;

それはそれらをうまく行う方法を忘れてしまったように特にうまく書かれていませんが、@ synthesizeディレクティブはアクセサを何度も書く必要をなくします。これは、Obj-C 1.0に大きく影響したことの1つです。

無料のコード、それをノックしないでください。

17
Warren Burton