Objective-Cのセッターメモリ管理
-
13-09-2019 - |
質問
Objective-Cのメモリ管理についてまだ少し混乱。私は私の混乱が正確に自動解放が何を意味するかに由来だと思います。
NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];
さて、私は私のビューコントローラのsetAccountDictionary方法でaccountDictionaryで何をすべきでしょうか?今私はちょうど返されているものに、インスタンス変数「accountDictionary」に設定してください。私はそれが保持いずれかに設定した後、返される1を解放すべきか?どのような私のセッターのコードブロックの外観のように、NSStringのののpropertylist方法が自動解放されることを考えるべきか。
私はtheBackendResponseを解放する場合は、ところで、私はaccountDictionaryを失うことになりますか?私がいないと仮定...
解決
の呼び出し[objectInstance autorelease]
は現在NSAutoreleasePool
にオブジェクトを追加します。そのプールがdrain
メッセージを受信すると、プール内のすべてのオブジェクトにrelease
を送信します。これらのオブジェクトのretainCountのいずれかが0になった場合、それらはその時点で割り当てが解除されています。自動解放の目的は、「将来のある時点」をリリースするオブジェクトをマークできるようにすることです。これは、新しく割り当てられたオブジェクトを返しますが、呼び出し側は返されたオブジェクトの所有権を取得する必要がないように、それを解放するメソッドのようなもののために特に便利です。この方法は、次のようになります。
- (id)myMethod {
id myObj = [[SomeClass alloc] init];
...
return [myObj autorelease];
}
彼らは、戻り値の所有権を取るかどうそれを無視したい場合は、 myMethod
の呼び出し側は戻り値をretain
でしょう。現在NSAutoreleasePool
が排出されると、myObj
は解放メッセージが表示されます。他のオブジェクトがそれを所有していない場合(すなわち、それにretain
メッセージを送信した)、それが割り当て解除されます。
このすべてがココアメモリ管理プログラミングガイド<に説明されています/>。あなたはすでにそれを読んだとしても、それは常に他の読み取り価値はあります。
だから、あなたの質問に答えるために:
まず、あなたはtheBackendResponse
を解放する必要があります。そうしない場合は、メモリリークが発生します。あなたは文字列で何accountDictionary
知っている必要はありません:それはtheBackendResponse
を保持しています参照を保持する必要がある場合。あなたは(theBackendResponse
を介して間接的alloc
経由または)その所有権を放棄しなければならないので、あなたは、それをrelease
'dので、あなたはautorelease
の所有権を持っています。
第二に、あなたは、それぞれ、そのオブジェクトまたは値への参照を保持する場合setAccountDictionary:
する引数を保持またはコピーする必要があります。
-(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メソッドでaccountDictionaryをrelease
する覚えておく必要があります:
- (void)dealloc {
[accountDictionary release];
[super dealloc];
}
可能な場合はNSViewController
を使用しているように見えるので、、私はあなたが、その場合にはヒョウ(OS X 10.5)にしていると仮定し、あなたはおそらく@property
と@synthesize
dゲッター/セッターを使用する必要があります。これを行うには、追加
@property (copy,readwrite) NSDictionary * accountDictionary;
クラス@interface
に宣言。そして、あなたのコントローラクラスの@synthesize accountDictionary;
ブロックで@implementation
ディレクティブを追加します。
他のヒント
一般的には、一つのオブジェクトやメソッドは、別のメモリを管理しているかを気にする必要はありません。他の誰かが何かを自動解放したという事実は、あなたとは無関係です。これは、の所有権のコンセプトを考えて簡単です。だから、retain
および他のいくつかの方法が所有権を主張し、release
とautorelease
はそれを放棄します。オブジェクトが別の参照を保持する必要がある場合、それは、それが必要としての所有権を主張すべきです。このように、setterメソッドは通常どちらか保持するか、または新しい値をコピーし、リリースや古い値を自動解放ます。
私は強くココアのメモリ管理ガイドラインを読んでお勧めする 。彼らはすべてのこと、長いまたは複雑じゃない、それはそれらを理解することは非常に重要です。
setアクセサメソッドは常にcopy
/古い値が新しい値を所有している唯一のオブジェクトである場合には、古いものをリリースする前に入ってくる値をretain
必要があります
-(void)setAccountDictionary:(NSDictionary*)newDict {
id old = accountDictionary;
accountDictionary = [newDict copy];
[old release];
}
accountDictionary
はnewDict
とnewDict
のカウントを保持するために呼ばれた場合は、 [accountDictionary release]
の呼び出し前に[newDict copy]
の呼び出しが保持カウントが0になったので、newDict
を解放させるような、1だった。
私たちは、古い辞書を解放し、新しい辞書をコピーする不正なコードの例として、ます:
-(void)setAccountDictionary:(NSDictionary*)newDict {
[accountDictionary release];
accountDictionary = [newDict copy];
}
、次のコードを持っています:
NSDictionary *dict = [obj accountDictionary];
[obj setAccountDictionary:dict];
これは不自然だが、それはセッター、accountDictionary
とnewDict
に同じインスタンスを参照することを示しています。保持カウントが1の場合、[accountDictionary release]
ラインは0に保持カウントを減少させ、したがって、メモリからインスタンスを解放します。 [newDict copy]
は現在、無効なインスタンスを参照します。
アップルは、いくつかの概念について説明します。メモリ管理アクセサメソッドの
あなたはObjective-Cの2.0を使用することができる場合、私はプロパティとドット構文で行くだろう。
プロパティのObjective-C 2.0の新機能で、自動アクセサの生成を提供します。
.hファイルでます:
@property (retain) NSDictionary* accountDictionary;
の実装でます:
@synthesize accountDictionary;
合成は、あなたのNSDictionaryのためのアクセサメソッドを生成します。 (あなたが独自の実装を提供したい場合は、あなたもそれを行うことができます)。