2009-06-09 10 views
2

Objective-Cメモリー管理についてまだ少し混乱しています。私は自分の混乱は、正確にオートリリースが意味するものに由来すると思う。Objective-Cセッターメモリー管理

NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding]; 
NSDictionary *accountDictionary = [theBackendResponse propertyList]; 
[viewController setAccountDictionary:accountDictionary]; 

ここで、私のView ControllerのsetAccountDictionaryメソッドのaccountDictionaryはどうすればよいですか?今はインスタンス変数 "accountDictionary"を返されるものに設定します。私はそれを保持されたものに設定し、返されたものをリリースする必要がありますか? NSStringのpropertyListメソッドがオートリリースされているので、私のセッターコードブロックはどのように見えるでしょうか?

ところで、私がBackendResponseをリリースした場合、accountDictionaryは失われますか?私はそうではないと思う...

答えて

14

[objectInstance autorelease]を呼び出すと、現在のNSAutoreleasePoolにオブジェクトが追加されます(独自の実装を提供する場合は、それも可能です)。そのプールはdrainメッセージを受信すると、プール内のすべてのオブジェクトにreleaseを送信します。これらのオブジェクトのいずれかがretainCountが0になると、それらのオブジェクトはその時点で割り当てが解除されます。オートリリースの目的は、「将来のある時」にリリースされるオブジェクトをマークすることです。これは、新しく割り当てられたオブジェクトを返すメソッドのようなもので、呼び出し元が返されたオブジェクトの所有権を取る必要がないように解放したい場合に特に便利です。この方法は、次のようになります。

- (id)myMethod { 
    id myObj = [[SomeClass alloc] init]; 

    ... 

    return [myObj autorelease]; 
} 

彼らは、戻り値の所有権を取るかどうそれを無視したい場合myMethodだろう、その後retain戻り値の呼び出し元。現在のNSAutoreleasePoolが流出すると、myObjはリリースメッセージを受け取ります。他のオブジェクトがそれを所有していない(すなわち、retainメッセージを送信した)場合、そのオブジェクトは割り当て解除されます。

このすべては、ココアMemory Management Programming Guideで説明されています。あなたがすでにそれを読んだとしても、それはいつも他の読書の価値があります。

だから、あなたの質問に答えるために:

まず、あなたはtheBackendResponseを解放する必要があります。あなたがしない場合は、メモリがリークされます。 accountDictionaryが文字列で何をするのかを知る必要はありません。参照を保持する必要がある場合は、theBackendResponseを保持します。あなたはallocなので、theBackendResponseの所有権を持っていますので、その所有権を譲渡する必要があります(releaseまたは間接的にautorelease経由)。

第2に、そのオブジェクトまたは値への参照をそれぞれ保持したい場合は、引数をsetAccountDictionary:に保持またはコピーする必要があります。標準のセッターメソッドは次のようになります(あなたがアトミックセマンティクスを必要としないと仮定):あなたが使用しているように見えるので

- (void)dealloc { 
    [accountDictionary release]; 
    [super dealloc]; 
} 

-(void)setAccountDictionary:(NSDictionary*)newDict { 
    if(newDict != accountDictionary) { 
    id tmp = accountDictionary; 
    accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back. 
    [tmp release]; 
    } 
} 

あなたはまた、deallocメソッドでrelease accountDictionaryに覚えておく必要がありますNSViewController、あなたはLeopard(OS X 10.5)を使用していると仮定します。可能であれば、@property@synthesize dゲッター/セッターを使用しているはずです。これを行うには、

@property (copy,readwrite) NSDictionary * accountDictionary; 

をクラス@interfaceに追加します。コントローラクラスの@implementationブロックに@synthesize accountDictionary;ディレクティブを追加します。

+0

印象的な答え。 –

+0

素晴らしいです、ありがとうございます。今分かります。私はUIViewControllerを使ってiPhone上に実際にいますが、明らかにObjective-C 2.0がまだ適用されています。私はこのために合成されたgetter/setterを使用するつもりはありませんが、将来私はそれを行います。再度、感謝します! – AriX

+0

これはやや間違っています。新しいオブジェクトを保持/コピーする前に古いオブジェクトを解放してはいけません。 'accountDictionary'が' newDict'を参照している場合は、まず 'release'を呼び出すと、早くリリースされます。私は複数のコードを追加することはできませんが、回答として代替ソリューションを追加します –

2

アップルは、アクセサーを実装するときにいくつかの概念を説明しています:Memory Management Accessor Methods
Objective-C 2.0を使用できるなら、プロパティとドット構文を使用します。 プロパティはObjective-C 2.0で新しく追加され、自動アクセサ生成を提供します。 .hファイルで
:実装で

@property (retain) NSDictionary* accountDictionary; 

@synthesize accountDictionary; 

合成は、あなたのNSDictionaryのためのアクセサメソッドを生成します。

+0

私はそれを行うことができましたが、それは私がバックグラウンドで何が起こっているのかを理解するのを助けません:) – AriX

4

一般に、1つのオブジェクトまたはメソッドは、他のどのようにメモリを管理しているか気にする必要はありません。誰かが何かをオートリリースしたという事実は、あなたと無関係です。 のオーナーシップという概念を考えるのは簡単です。だからretainと他のいくつかの方法が所有権を主張し、releaseautoreleaseがそれを放棄する。オブジェクトが別のオブジェクトへの参照を保持する必要がある場合、オブジェクトは必要な限り所有権を主張する必要があります。したがって、setterメソッドは通常、新しい値を保持またはコピーし、古い値を解放または自動解放します。

the Cocoa memory management guidelinesを強くお勧めします。それらは長くて複雑なものではありません。それらを理解することは非常に重要です。

+0

OK。私は実際にそれらを読んでいない、今行う: – AriX

3

アクセサ設定方法古い値が新しい値所有している唯一のオブジェクトである場合には、古いを解放する前にする必要があり、常にcopy/retainの着信値:

-(void)setAccountDictionary:(NSDictionary*)newDict { 
    id old = accountDictionary; 
    accountDictionary = [newDict copy]; 
    [old release]; 
} 

newDict呼ばaccountDictionary場合newDictの保持カウントが1の場合、[newDict copy]へのコールの前に[accountDictionary release]を呼び出すと、保持カウントが0になるため、newDictが解放されます。私たちは古い辞書を解放し、新しい辞書をコピーする不正なコードの例として、

-(void)setAccountDictionary:(NSDictionary*)newDict { 
    [accountDictionary release]; 
    accountDictionary = [newDict copy]; 
} 

と次のコードを持っている:

NSDictionary *dict = [obj accountDictionary]; 
[obj setAccountDictionary:dict]; 

をそれは不自然だが、それが示しますセッターでは、accountDictionarynewDictは同じインスタンスを指しています。保持カウントが1の場合、[accountDictionary release]行は保持カウントを0に減らし、メモリからインスタンスを解放します。 [newDict copy]は無効なインスタンスを参照するようになりました。

+0

+1合意。このような状況が発生する可能性のある例を教えてください。 – Stunner