2010-12-28 10 views
2

こんにちは。私はこの質問が尋ねられたことは知っていますが、Objective-Cのメモリ管理の明確なイメージはまだありません。私はそれをかなりよく把握しているように感じますが、次のコードについてはまだ正しい答えがほしいと思います。私は明確にするために誰かが好きな一連の例を持っています。インスタンス変数に値を設定iPhoneのメモリ管理(特定の例/質問あり)

は私がNSMutableArray変数を持っていると言います。私のクラスでは、初期化するときにretainと呼ぶ必要がありますか?

私は1にretain回数を設定するので、私はそれにretainを呼び出す必要がありませんまだ[[NSMutableArray alloc] init]

fooArray = [[[NSMutableArray alloc] init] retain]; 

または

fooArray = [[NSMutableArray alloc] init]; 

を行うやっていますか?一方、私が知っているメソッドを呼び出すと、autoreleaseオブジェクトが返ってきたら、確かにretainと呼ぶ必要があります。これと同じように:

fooString = [[NSString stringWithFormat:@"%d items", someInt] retain]; 

プロパティ:私は@propertyの自動セッターがどのように機能するかについて少し困惑しているので

私はretainについて尋ねます。

fooArray@propertyに設定してretainに設定した場合、Objective-Cは自動的に次のセッターを自動的に作成します。

- (void)setFooArray:(NSMutableArray *)anArray { 
    [fooArray release]; 
    fooArray = [anArray retain]; 
} 

私はこのようなコードを持っていたのであれば、:self.fooArray = [[NSMutableArray alloc] init];を(私は有効なコードであると信じている)、Objective-CのはfooArrayに割り当てられた値にretainを呼び出すsetterメソッドを作成します。この場合、retainのカウントは実際に2になりますか?プロパティの値を設定する

正しい方法:

私はこの上の質問と、(おそらく)議論がある知っているが、@propertyを設定するための正しい方法でありますか?

これは?

self.fooArray = [[NSMutableArray alloc] init]; 

またはこれは?

NSMutableArray *anArray = [[NSMutableArray alloc] init]; 
self.fooArray = anArray; 
[anArray release]; 

これらの例についていくつか説明しておきたいと思います。ありがとう!

答えて

3

可能であれば、特に多くのメモリの問題を回避するのに役立つので、オブジェクトを扱う場合は、アクセサーを使用するのが理想的です。そうでもインスタンス変数のために、あなたが行う必要があります。

self.fooArray = ...; 

代わりの

fooArray = ...; 

を使用すると、オブジェクトのインスタンス変数のプロパティを宣言する必要がある理由は、メモリ管理がやや複雑であるためであり、それを再作成します手で毎回厄介です。

self.foo = [[NSMutableArray alloc] init]; 
:あなたは、この(と仮定fooが保持されている)のような何かを行うときに、インスタンス変数が2の保持カウントを持っていることについて正しい

- (void)setFoo:(NSArray *)aFoo { 
    if (foo == aFoo) { 
     return; 
    } 
    NSArray *oldFoo = foo; 
    foo = [aFoo retain]; 
    [oldFoo release]; 
} 

:非アトミックの正しいセッターは、プロパティは次のようになり保持しました

最初の保持カウントはallocから、2番目は合成されたセッターからのカウントです。

// longer, explicit version, releases immediately (more efficient) 
NSMutableArray *aFoo = [[NSMutableArray alloc] init]; 
self.foo = aFoo; 
[aFoo release]; 

// autoreleased, not so bad unless you're a memory management freak 
self.foo = [[[NSMutableArray alloc] init] autorelease]; 

// an even shorter version of the above 
self.foo = [NSMutableArray array]; 

プライベートプロパティを作成するには、それらを.m実装ファイルのクラス拡張として宣言できます。例を挙げれば、名前を持つ単純なPersonオブジェクトと、オブジェクトがあるデータベースに保存されているかどうかを単に示すブール値のプロパティdidSaveを考えてみましょう。これを外部に公開するのではなく、実装ファイル内のプロパティの利点を維持したいので、ヘッダファイルを作成するにはすべてのインスタンス変数(public、private、protected)とpublicプロパティのみを作成します。

// Person.h 

@interface Person { 
    NSString *name; 

    @private 
    BOOL didSave; 
} 

@property (nonatomic, retain) NSString *name; 

@end 

しかし、実装内部のプライベートプロパティを宣言します。私は、プロパティの配列を割り当てるための一時配列のオブジェクトを作成する知っている

// Person.m 

// property is declared as a class extension, making it 
// invisible to the outside world. 
@interface Person() 
    @property BOOL didSave; 
@end 

@implementation 

// synthesize as normal 
@synthesize name, didSave; 

@end 
+0

返事ありがとう、Anurag。変数を他のクラスからアクセスできるようにする必要がないときは、プロパティを避けようとしています。 n00bの質問の種類ですが、他のクラスからアクセスできないプロパティを持つことはできますか? – donkim

+0

編集のおかげで、Anurag。あなたが気にしないなら、私はいくつかの明確な点を求めています。.mの@interfaceにcanSave変数を宣言できますか?公開されていない変数は暗黙のうちに既にプライベートであり、そのようにマークする必要があるように少し冗長に思えます。 – donkim

+0

私はプライベートインスタンス変数部分についてお聞きしますが、残念ながらこれはObjective-Cで実装の詳細をプライベートに保つために得られる最も近いものです。変数をプライベートとしてマークしないと、デフォルトでは保護されたアクセス権が得られます。これは必要な場合とそうでない場合があります。 – Anurag

0

まず第一には、この行で:

fooArray = [[NSMutableArray alloc] init]; 

fooArrayが自動的に1

第二の保持カウントを持っています、はい、それは2だとセッターの実装上のあなたの推測は正しいです。

第三に、後者は、AppleのObject Ownership Policy、言葉allocまたはnewから始まる、またはcopyは、呼び出し側によって所有され含まれている任意の方法によれば、右

4

です。

オブジェクトの所有権を取得するには、retainにする必要があります。

最初の例では、すでにオブジェクトを所有しているため、retainは不要です。

これを行うための正しい方法は:

fooArray = [[NSMutableArray alloc] init]; 

autoreleasedオブジェクトは、現在の自動解放プールによって所有されているので、あなたがそれらの所有権を得るためにそれらにretainを呼び出す必要がありますので、この例は正しいです:

fooString = [[NSString stringWithFormat:@"%d items", someInt] retain]; 

これは、同様に正常に動作します:

self.fooString = [NSString stringWithFormat:@"%d items", someInt]; //retained by property setter 

とプロパティのセッターを使用して、最後の例のために、これはそれを行うための正しい方法のようになります。

NSMutableArray *anArray = [[NSMutableArray alloc] init]; 
self.fooArray = anArray; 
[anArray release]; 

代わりに上記を行うために有するので、私は以下のソリューションをお勧めしたい:

self.fooArray = [NSMutableArray arrayWithCapacity:10]; 

arrayWithCapacity:は、オートレリースされたNSMutableArrayを返します。これは、プロパティ設定メソッドでretain -edです。 :)

+0

は良いのですが、どのような問題がself.fooArray =に関連付けられている[[NSMutableArrayののalloc]のinit];理由メモリリークを起こします。 – Ishu

+1

@Ishu Gupta、その行に 'alloc'を呼び出したのでオブジェクトを所有しているのでメモリリークがあり、' @ property'セッターにはおそらく 'retain'修飾子があるので、その割り当ての最終結果は'self.fooArray = [[[NSMutableArray alloc] init] retain]'、したがってリークです。 –

+0

私はこれではっきりしていなかった、今私のための画像は明らかです。 – Ishu