2008-08-17 5 views

答えて

38

-[NSObject dealloc]が実行される前に、オブザーバを削除する必要があります。そうすれば、クラスの-deallocメソッドで実行することができます。

それよりも優れていますが、観測を行っているオブジェクトを所有しているものは、それが完了したことを示すことができ、(最終的に)割り当てを解除されるという決定論的な点があるでしょう。そうすることで、実際に割り当てを解除した時点に関係なく、観測を行うことがもう必要なくなったときにすぐに観察を停止することができます。

これは、ココアのオブジェクトの存続期間が、それがあると思われるように決定的ではないため、留意することが重要です。さまざまなMac OS Xのフレームワーク自体は、あなたのオブジェクト-retain-autoreleaseを送り、そうでないと思われるかもしれない寿命を延ばします。

さらに、Objective-Cガベージコレクションに移行すると、-finalizeは非常に異なる時刻に(非常に異なるコンテキストで)、-deallocよりも実行されることがわかります。一つは、ファイナライズは別のスレッドで行われるので、実際にはできません-removeObserver:forKeyPath:を別のオブジェクトに-finalizeメソッドで安全に送信できません。 -dealloc-finalizeにおけるメモリ(および他の希少資源)へ

スティック管理、および所有者は、あなたが、確定時点でそれで行われているオブジェクトを伝える持っている別の-invalidateメソッドを使用します。 KVOの観測結果を削除するようなことをしてください。コードの意図が明確になり、微妙なバグが少なくなります。

+7

に他のメモリクリーンアップを行います。 – Jeff

+0

その徹底的な説明をありがとう! OS X 10.7ライオンのよう –

+0

は、-removeObserver 'もあります:forKeyPathは:コンテキスト:'、あなたが-addObserver 'に渡された同じコンテキストに渡すことができます:forKeyPath:オプション:コンテキスト:'。ユニークなコンテキストを渡すことで、あなたがあなたを削除したときに他人の観察を削除しないようにします。 –

5

私は苦しい経験から得た追加情報:ガベージコレクションの実行中にNSNotificationCenterが弱参照をゼロにしていますが、KVOはそうではありません。したがって、GCを使用しているときにNSNotificationCenterオブザーバを削除しなくても済むようにすることができます(ただし、retain/releaseを使用する場合は、オブザーバを削除する必要があります)が、KVOオブザーバは削除する必要があります。

+0

これはどこかに書かれていますか? – hpique

2

Chrisは、「メモリとその他の乏しいリソースに管理してください。」という-deallocと-finalizeの管理に関するコメントにはっきりと同意します。何度も、dealloc関数でNSTimerオブジェクトを無効にしようとする人がいます。問題は、NSTimerがターゲットを保持していることです。したがって、NSTimerのターゲットが自己であれば、deallocは呼び出されることはありません。その結果、メモリリークが発生する可能性があります。

-invalidateでの無効化と私は経験から、あなたのオブザーバーを削除しない場合は、無限のクラッシュに届きます痛みを確認することができ、あなたのdeallocfinalize.

関連する問題