15

synthesizeプロパティ名をオーバーライドしてディレクティブの目的を理解しようとしています。次のように定義されたインターフェイスがあるとします。

@interface Dummy ... {
    UILabel *_dummyLabel;
}

@property (retain, nonatomic) UILabel *dummyLabel;

そして、実装ファイルには、次のものがあります。

@synthesize dummyLabel = _dummyLabel;

私が理解していることから、「dummyLabel」はインスタンス変数「_dummyLabel」の単なるエイリアスです。self._dummyLabelとself.dummyLabelに違いはありますか?

4

5 に答える 5

24

はい。self._dummyLabelは未定義ですが、そうでは_dummyLabelありません。

ドット構文は単純なメソッド呼び出しに拡張されるため、プロパティに固有のものではありません。-(id)someObjectたとえば、の場合のように、と呼ばれるメソッドがある場合object.someObject、それはあなたが書いたかのようになります[object someObject];

self.dummyLabel  //works
self._dummyLabel //does not work
dummyLabel       //does not work
_dummyLabel      //works
[self dummyLabel];  //works
[self _dummyLabel]; //does not work
于 2010-09-27T10:17:28.023 に答える
17

あなたの理解は間違っています。dummyLabelはプロパティの名前であり、インスタンス変数のエイリアスではありません。インスタンス変数は。と呼ばれるだけ_dummyLabelです。Dummyしたがって、呼び出されたインスタンスには次のことが当てはまりますmyObject

  • [myObject dummyLabel]作品
  • myObject.dummyLabel作品
  • [myObject _dummyLabel]失敗する
  • myObject._dummyLabel失敗する
  • myObject->dummyLabel失敗する
  • myObject->_dummyLabelivarの可視性に依存します(@public、、)@private@protected
  • [myObject valueForKey: @"dummyLabel"]作品
  • [myObject valueForKey: @"_dummyLabel"]の実装に依存します(つまり、 returns+accessInstanceVariablesDirectlyのデフォルトの場合に機能します)。+accessInstanceVariablesDirectlyYES
于 2010-09-27T10:23:43.540 に答える
13

プロパティよりもivarに別の名前を付けることの利点は、どちらかにアクセスしているときにコードで簡単に確認できることです-Andre K

「コメント」ボタンが見つからないため、「回答」として投稿する必要があります。

アンドレのコメントを拡張したかっただけです-合成されたプロパティとバニラ変数をいつ使用しているかを知ることで、(特にセッターの場合)変数が素敵なセッターのおかげで自動的に保持/コピー/解放されるときと手で操作します。

もちろん、あなたが正しいことをしているなら、あなたはおそらくオブジェクトを適切に保持/解放するためにセッターの助けを必要としないでしょう!ただし、デフォルトの合成セッター/ゲッターの代わりにカスタムセッター/ゲッターを使用している場合など、 ivarをself.ivar代わりに参照すると役立つシナリオもあります。_ivarおそらく、プロパティを変更するたびに、NSUserDefaultsにも保存する必要があります。したがって、次のようなコードがある可能性があります。

@interface SOUserSettings : NSObject {

BOOL _autoLoginOn;

}

@property (nonatomic, assign) BOOL autoLoginOn;

@end

@implementation SOUserSettings

@synthesize autoLoginOn = _autoLoginOn;

- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {

   _autoLoginOn = newAutoLoginOnValue;
   [[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"];
}

@end

注:これは単なる例示的なコードであり、何千もの問題がある可能性があります。

したがって、コードに次のような行がある場合は、_autoLoginOn = YESNSUserDefaultsに保存されないことがわかりますが、使用する場合は、self.autoLoginOn = YES何が起こるかが正確にわかります。

との違いは_autoLoginOnself.autoLoginOn単なるセマンティックではありません。

于 2011-04-22T05:10:27.143 に答える
0

_dummyLabelの名前をdummyLabelに変更することに大きな利点はありません

一部のObjCランタイムでは、クラスのユーザーにインスタンス変数を非表示にするのに苦労しています。彼らにとって、インスタンス変数に接頭辞(または接尾辞)を付けると、誰かが変数をいじってほしくないことが明確になります(またはより明確になります)。しかし、あなたはあなたの公の行事にその大騒ぎをしたくありません。これはあなたがそれを降りることを可能にします。

また、新しい名前のセット(setLastnameとsetSurname)を持つ新しいAPIのセットと同時に、1つの名前のセットを持つ古いインターフェイスを維持する必要がある場合にも役立ちます。

于 2010-09-27T13:36:16.703 に答える
0

古い投稿ですが、ゲッターとセッターを介して変数にアクセスすることをお勧めします(つまり、ドット表記を使用することをお勧めします)。フィールドに直接アクセスする(_ivar)ことは、フィールドを初期化する場合にのみ強くお勧めします。

いくつかの良いAppleの記事があります: https ://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

最後の段落:

プロパティが設定された時点では、オブジェクトの残りの部分がまだ完全に初期化されていない可能性があるため、初期化メソッド内から常にインスタンス変数に直接アクセスする必要があります。カスタムアクセサメソッドを提供しない場合や、独自のクラス内からの副作用を知らない場合でも、将来のサブクラスが動作をオーバーライドする可能性があります。

于 2013-03-12T18:14:05.483 に答える