カスタムオブジェクトのNSMutableArrayがある場合、メモリの問題を引き起こさずに配列を簡単にクリアするにはどうすればよいですか?カスタムオブジェクトクラスには、インスタンス変数などを正しく解放するdeallocメソッドが含まれていると仮定します。
たとえば、NSArrayの「removeAllObjects」メソッドを使用しても問題ありませんか?
はいの場合-これはどのように機能しますか-「removeAllObjects」は、オブジェクトを削除するときに各オブジェクトの「dealloc」メソッドを呼び出しますか
いいえの場合-使用する最も簡単な方法は何ですか?
EDIT(4返信後)-すばらしい返信後の明確化の最後の質問-保持するように設定したカスタムオブジェクトのインスタンス変数/プロパティについてまだよくわかりませんか?これらは、カスタムオブジェクトクラスの「dealloc」メソッドを介してのみ解放されるようです。[スーパーリリース]とともに手動でこれを行います。
したがって、配列をクリアし直し、removeAllObjectsを実行してから、NSArrayがカスタムオブジェクトに「解放」を発行したが、「dealloc」を呼び出さなかった場合、インスタンス変数はどのように解放されますか?
removeAllObjects
は、配列からオブジェクトを削除します。このプロセスにより、オブジェクトにリリースメッセージが送信され、参照カウントが減少します。参照カウントがゼロに達すると、オブジェクトは割り当て解除されます。
リークするので、このようにしないでください。
NSObject *object = [[NSObject alloc] init]; + 1
[array addObject:object]; + 1
[array removeAllObjects]; - 1
=======
= + 1 -> Leak
これは正しい方法です:
NSObject *object = [[[NSObject alloc] init] autorelease]; + 1 (from alloc) - 1 (from autorelease)
[array addObject:object]; + 1
[array removeAllObjects]; - 1
=======
= 0 -> Object will be deallocated
RemoveAllObjectsを呼び出す代わりに、配列を解放することもできます。配列の割り当てが解除されると、その中にあるすべてのものが解放され、オブジェクトへの参照が他にない場合は、割り当てが解除されます。
はい、removeAllObjects
を呼び出します。念のため、配列にオブジェクトを追加するとき、またはオブジェクトを含む配列を作成するときは、retain
を呼び出さないでください。これは自動的に行われます。
dealloc
についても、これは自動的に行われ、いつ予測することはできません。
Deallocに必要なのは配列オブジェクト自体だけです。つまり、インスタンス変数またはivarであると想定しますか?
すべてが良好であることを確認するには、製品->分析を使用してアナライザーを実行します。そして、Leaksインストゥルメントを使用してInstrumentsでアプリにプロファイルを与え、コードがメモリリークを引き起こしていないことを確認します。
dealloc
メソッドが直接呼び出されることはありません。すべてがretain
/release
メカニズム(および参照カウントの原則)を介して行われます。つまり、これはrelease
メソッドではなく、直接呼び出されるdealloc
です。 dealloc
メソッドは、最後のrelease
呼び出しによってオブジェクトの参照カウント(retainCount)がゼロに達した場合にのみランタイムによって呼び出されます。つまり、オブジェクトは実際にはメモリから解放され、誰も使用しませんもう。
NSArray
およびCocoaのすべてのコンテナークラス(NSDictionary
、NSSet
、...)は、それらの値を保持します。したがって、NSArray
のようなコンテナーにオブジェクトを追加すると、その値がretain
になります。そして、その値を削除すると(removeAllObjectsを呼び出すときを含む)、それはrelease
になります。
メモリ管理のルールは簡単に実行できます。ただし、release
、autorelease
を呼び出した場合は、alloc
またはretain
を呼び出すだけでよいという重要なルールがあります。またはcopy
メソッド。これは常に、alloc
/retain
/copy
がrelease
/autorelease
を呼び出すようにしたオブジェクトの責任です。保留中のalloc
/retain
呼び出しなしでcopy
/release
/autorelease
を残さないでください(そうしないと、リークが発生します) 、ただしrelease
/autorelease
/alloc
を自分で呼び出さなかった場合は、決してretain
/copy
を呼び出さないでください。
良い例1:
MyClass* obj = [[MyClass alloc] init]; // here you do an alloc
[myArray addObject:obj]; // the NSArray "myArray" retains the object obj
// so now you can release it, the array has the responsability of the object while it is held in the array
[obj release]; // this release balance the "alloc" on the first line, so that's good
[myArray removeAllObjects]; // there the object held by the array receive a release while being removed from the array. As nobody retains it anymore, its dealloc method will be called automatically.
良い例2:
MyClass* obj = [[MyClass alloc] init]; // here you do an alloc
[myArray addObject:obj]; // the NSArray "myArray" retains the object obj
// so now you can release it, the array has the responsability of the object while it is held in the array
[myArray removeAllObjects]; // there the object held by the array receive a release while being removed from the array. But your own code still retains a reference to it (because of the "alloc" on first line) so it won't be removed from memory right now
[obj release]; // this release balance the "alloc" on the first line, and as nobody retains the object anymore, its dealloc method will be called and it will be deallocated from memory
良い例3:
MyClass* obj = [self getSomeObjectFromAnotherMethod]; // here you don't have an "alloc" on this line
[myArray addObject:obj]; // the array retains the object
[myArray removeAllObjects]; // the array release the object while it removes it from the array
// no need to call "release" here as there is no "alloc" done in the scope of this code
悪い例:
MyClass* obj = [self getSomeObjectFromAnotherMethod]; // here you don't have an "alloc" on this line
[myArray addObject:obj]; // the array retains the object
[myArray removeAllObjects]; // the array release the object while it removes it from the array
[obj release]; // Crash here! obj does not exists anymore and has been deallocated from memory before this line!
基本的にremoveAllObjects
メソッドはrelease
メッセージをすべてのオブジェクトに送信します。 releaseメソッドはオブジェクト参照カウントをデクリメントします =。また、オブジェクトの参照カウントが0
に達すると、dealloc
メッセージがオブジェクトに送信されます。
あなたの質問に対する答えは、[array removeAllObjects]
への電話は完全に安全です。ちなみに、配列が必要なくなった場合は、[array release]
を直接呼び出すことができます。これにより、配列だけでなくそのすべてのオブジェクトが解放されます。