2011-09-01 9 views

答えて

0

ivar(インスタンス変数)を安全に保つことは、ゲッターとセッターを介してのみアクセスできるようにすることです。

私は仕事がバックエンドサーバから必要なデータをロードするために行われるように、私は通常私のIVARを強調します性質上遅延読み込みを行いたい場合は/保存された:私は時々これを行う理由はここに

+2

より良い方法は、ドット構文を使用しないことです。 – jer

+4

@synthesizeは、ドット構文と完全に直交しています(一般的にはプロパティです)。 –

1

ですファイル/ what-have-youは初めて読み込まれるだけです。たとえば:だからここ

- (NSMutableArray *)recentHistory; 
{ 
    if (_recentHistory == nil) 
    { 
     // Get it and set it, otherwise no work is needed... hooray! 
    } 

    return _recentHistory; 
} 

プロパティへの呼び出し[instanceOfClass recentHistory](またはinstanceOfClass.recentHistory)は、データをロードするか、単に、すでにロードされたデータを返す必要があるかどうかを確認するためにIVARをチェックします。

このようにすべてのプロパティを宣言するのは残念です。

希望に役立ちます。

+2

しかし、これには実際にアンダースコアを使用する必要がありますか、それとも単にコンベンションとしての意味ですか? 'recentHistory'メソッドの中でインスタンス変数' recentHistory'または 'self-> recentHistory'を使用するだけで、プロパティ名' self.recentHistory'や '[self]を使わないようにすることができますrecentHistory] ​​'と再帰を引き起こします。 –

+0

いいえ、慣習として。 Appleのコードでも同様のことが判明しているので、人々がそれを使用する理由が考えられます。 iVarとプロパティを持つアイデアは時には過度に使用されることもありますが、これはそれ以降のことだと思います。 –

3

場合によっては、裏で起こっていることを理解するのに役立ちます。あなたはこれによりこの

@property (nonatomic, retain) Foo *foo; 

を見ると、基本的な実装

@synthesize foo=_foo; 

では、コンパイラは基本的にあなた

Foo *foo = nil; 

-(Foo *) foo { 
    return _foo; 
} 

-(void) setFoo:(Foo *)val { 
    if(_foo != val) { 
     [_foo release]; 
     _foo = [val retain]; 
    } 
} 

ために、このコードを生成するというこの方法を意味し、以下の構文砂糖ですパブリックプロパティを参照するときは、self.fooの生成されたアクセサリを使用してヒットし、あなたのクラスのインスタンス変数は、_fooを参照することができます。 XCode 4の前に、2つの間で混乱するのは簡単でした。

self.foo = foo1; 

foo = foo2; 

これは完全に正当なものであり、カップルレベルで問題を引き起こす可能性があります。 2行目はアクセサーを使用しないので、foo2は保持されず、ガベージコレクションによって早期に取得される可能性があります。さらに悪いことに、2行目は、以前の値を解放するアクセサを使用しないため、メモリリークが発生します。

要約すると、新しい手法では、プロパティのgetterとsetterが作成され、カプセル化に使用されるインスタンス変数に使用される名前も指定できます。

+0

良い説明。ちょうどニックピッキング: 'if(_foo!= nil)[_foo release];'新しい値が以前の値と違うかどうかテストするのではなく、無駄かもしれないコンパイラがテスト対nilを生成していません。例については、http://stackoverflow.com/questions/3924463/how-is-retain-setter-implemented-with-synthesize/3925204#3925204を参照してください。 – jv42

+0

'Foo * tmp = [Foo foo];でコードを実行してみてください。 self.foo = tmp; self.foo = tmp; 'それがブームになるのを見る。 – jv42

+0

私はその答えを私のiPadに打ち明けましたが、私は正確な実装を100%確信していませんでしたが、本当にあなたのメモリ管理を処理し、衝突を回避するという事実を強調したいと思いました。ヘッドアップをありがとう! – jerrylroberts

1

上記のすべての回答に自分の考えを追加したかっただけです。

私の場合、主に私のクラスを事故から安全に保つために使用します。

私の.hファイルで、私はivarsのないプロパティだけを宣言します。 .mファイルでは、上記の@synthesizeパターンを使用して、実際のivarを自分自身を含めて、合成/動的アクセッサを強制的に使用するようにし、そうでなければ直接ivarsを使用しないようにします。あなたはあなたのivarの名前に何かを使うことができ、それを強調するだけではありません。例えばあなたができる:

@synthesize foo = _mySecretFoo; 
@synthesize bar = oneUglyVarBecauseIHateMyBoss; 

をこのように、あなたの上司は、唯一のバーを見るであろう、そしてあなたはそれがはるかに容易に見つけるだろう、したがって、より安全な、バーアクセサを使用するために - あなたは、ドット表記法やメッセージを使用するかどうか。

iは、プライベート実装およびカプセル化を強制することはありません。このよう

@property (getter=foo, setter=setFoo, ...) _mySecretFoo; 
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss; 

、他の上にこのアプローチを好む、それはXcodeのはあなたのために同じことを行うことができますだけ余分なタイピングです。覚えておくべきことは、プロパティはイヴァールと同じではありません!あなたはイヴァールよりも多くの特性を持つことができます。

+0

私がこの権利を読んだら、明示的にivarsを '@implementation {...}'ブロックで宣言せずにこれを行います。 'oneUgly'を参照することがないなら、' @synthesize bar = oneUgly; 'を使う利点は何ですか?どうして '@synthesize bar;'をしないのですか?それは 'bar = 123.0'と書くなど、あなたのやり方が間違っているからですか? –

+0

は、@interface {}ブロックで象牙を宣言することを意味します。はい、bar = 123を使用するとエラーが発生しますが、それは上記のパターンを使用する理由ではありません。 このパターンは、appleのdocs: '@syntheize age = numberOfYears;の例のように、実装を完全に隠している間にパブリックインターフェイスを公開することができる便利な機能です。' SomeAccount * account = [SomeAccount defaultAccount ]; self.account = account; 'これは私のコード記述スタイルなので、エラーを心配する必要はありません。純粋に利便性とコーディングスタイルです。 –

関連する問題