19

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=ディレクティブで物事を複雑にしなければならないのか私はまだ理解していません。

4

2 に答える 2

30

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

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

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

id _delegate;

と:

@synthesize delegate=_delegate;

アンダースコアプレフィックスを使用しないという以前のアドバイスは、コンパイラの現在の方法とデフォルトの動作に明らかに同意しなかったため、削除しました。ただし、私が知る限り、メソッド名にアンダースコアプレフィックスを使用するのはまだ不十分な形式です。

また、少なくとも1人の人が私の回答の最初の行を「本当に複雑ですか?」と解釈していることに気づきました。見下すように。それがたった一人の印象だったといいのですが、私は絶対に軽蔑するつもりはありませんでしたが、@synthesize xxx=_xxx;指令が物事を複雑にするというOPの主張を中心に私の応答を組み立てようとしていました。あなたが始めているときに吸収することがたくさんあります。うまくいけば、新しい「デフォルトで合成」動作により、新規参入者の負担が軽減されます。

于 2011-04-28T07:04:07.393 に答える
17

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

@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-C1.0についてひどくひどいことの1つです。

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

于 2011-04-28T07:22:53.050 に答える