8

重複の可能性:
cocoa object-c クラスの変数の前にあるアンダースコアはどのように機能しますか?


注:これを理解しようと探し回っている人々のために、私は混乱の原因を突き止めました。.h には、次のものがありました。

...
@interface myClass : parentClass {
className *variableName:
}

@property (strong, nonatomic) className  *variableName;
...

これにより、self.variableName と _variableName が .m 内の 2 つの異なる変数になります。私が必要としたのは:

...
@interface myClass : parentClass {
className *_variableName:
}

@property (strong, nonatomic) className  *variableName;
...

次に、クラスの .m では、self.variableName と _variableName は同等です


iOS 5.0+ プロジェクトをターゲットとする ARC を使用した最新の Xcode 4.5+ では、古いスタイルと比較して_variableNameoverを使用する明確な利点 (ランタイム効率、速度など) がありますか?self.variableName@synthesize variableName

_variableName私の理解では、Xcode 4.5+は同等のデフォルト アクセサーを作成し、self.variableName使用しない唯一の理由は@synthesize variableName、iVar と渡された変数の間の混乱を避けることです。正しいですか?

私にはself.variableName、 iVar にアクセスするために使用するだけで、どの変数を探しているかが最も簡単で明確に思えます。と入力する以外に、を使用する利点はあり_ますか?self._variableName

4

2 に答える 2

17

私の理解では、Xcode4.5以降はself.variableNameと同等のデフォルトのアクセサー「_variableName」を作成します。「@synthesizevariableName」を使用しない唯一の理由は、iVarと渡された変数の混同を避けるためです。

この場合、_variableNameはアクセサーではなく、コンパイラーによって自動的に生成され、自動的に@synthesizedセッターおよびゲッターで使用されるivarです。self.variableName一般に、キー値の監視やバインディングなどがそのプロパティで機能するように、可能な限りアクセサを使用するのが最善であると考えられています(つまり)。

ivarに直接アクセスする場合、構造体のデータにアクセスするのと同じ方法で、ダイレクトメモリアクセスを介してアクセスします。ivarを所有するオブジェクトへのポインタを取得し、メモリアドレスをオフセットして、その場所のメモリの読み取りまたは書き込みを試みます。ドット表記(self.variableName)を使用すると、アクセサメソッドを呼び出してそのプロパティを設定または取得し、その過程で次のようなさまざまなことを実行できます。

1)ロック:プロパティが複数のスレッドで使用され、atomicプロパティである場合、ランタイムは自動的にいくつかのロックを実行して、プロパティが複数のスレッドから同時にアクセスされないようにします。オブジェクトが複数のスレッドで使用されることを意図していない場合はnonatomic、プロパティ宣言でヒントを指定して、合成されたアクセサーがロックをスキップするようにすることができます。

2)Key-Value通知:プロパティのデフォルトのセッターは、プロパティが変更されたときに通知を送信する-willChangeValueForKey:andを呼び出します。-didChangeValueForKey:これは、バインディングが使用されている場合に適切に更新するため、およびその他のKey-Value監視のために必要です。

3)カスタムアクセサーの動作:独自のセッターとゲッターを作成することになった場合、それらの中に実装するカスタムのもの。

技術的には、ivarに直接アクセスする方がアクセサーを使用するよりも高速ですが、パフォーマンスに大きな違いが生じる状況はほとんどなく、最適化が時期尚早である可能性があります。上記のメリットをすぐに利用できるとは思わない場合でも、後でアクセサを使用して、後でその機能の一部が必要になった場合に、すべてのインスタンスを変更する必要がないようにすることをお勧めします。その変数にアクセスすること(そしておそらくその過程で予期しない新しいバグを作成すること)。

さらに、ivarに直接アクセスしていて、クラスをカテゴリまたはサブクラスにリファクタリングすることになった場合、通常はivarを@protected変数として宣言する必要があるため、面倒になります。アクセサを使用している場合は、これを行う必要はありません。

init一般的に、私は、、、deallocおよびプロパティのアクセサーで直接ivarにのみアクセスしようとします。多くのエンジニアはこの経験則に従います。これは、アクセサで発生するカスタム処理によって、オブジェクトがinit「ing」またはdealloc「ing」されているときに予期しない動作が発生する場合があるためです。たとえば、アクセサ内の何かがオブジェクトまたはオブジェクトに何かを引き起こしretainたりrelease、オブジェクトへのゼロ化弱参照を形成したりする場合、で使用するとクラッシュが発生しdeallocます。

于 2013-01-01T18:33:01.170 に答える
5

最新の Xcode@synthesizeではオプションです。デフォルトでは、省略@synthesizeは書き込みと同じです

@synthesize someName = _someName;

使用する唯一の理由は、プロパティの値を格納するために作成されたインスタンス変数の名前@synthesize変更することです。たとえば、

@synthesize someName = someSpecialName;

を使用self.variableNameして変数にアクセスする場合は、インスタンス変数にアクセスする短いメソッドであるプロパティを使用します。メソッドのディスパッチは非常に高速ですが、変数へのアクセスの同期など、追加のサービスを実行する場合があります (これは、プロパティ宣言でatomic指定した場合と指定しなかった場合に当てはまります)。nonatomicそのような場合、経由のアクセスself.variableNameは多少遅くなります。タイトなループで行われた場合、これは潜在的に違いを生む可能性があります. を使用して、基になるインスタンス変数に直接アクセスしたい場合があるのはそのためです_variableName

于 2013-01-01T17:56:13.537 に答える