23

別のオブジェクトバーからKVO通知を受信するようにオブジェクトfooを登録した場合(addObserver:...を使用)、fooの割り当てを解除した場合、-deallocのbarにメッセージを送信する必要がありますか?removeObserver:forKeyPath:

4

3 に答える 3

39

-removeObserver:forKeyPath:実行前にオブザーバーを削除するために使用する必要があるため、クラスのメソッドで-[NSObject dealloc]それを行うとうまくいきます。-dealloc

それよりも良いのは、観察を行っているオブジェクトを所有しているものは何でも、それが完了し、(最終的に) 割り当てが解除されることを伝えることができる決定論的なポイントを持つことです。そうすれば、実際にいつ割り当てが解除されたかに関係なく、監視を行っているものが不要になったときに、すぐに監視を停止できます。

Cocoa のオブジェクトの有効期間は、一部の人々が考えているほど決定論的ではないため、これは心に留めておくことが重要です。さまざまな Mac OS X フレームワーク自体-retainオブジェクトとを送信し、-autorelease他の方法で考えられるよりも寿命を延ばします。

-finalizeさらに、Objective-C ガベージ コレクションに移行すると、以前とはまったく異なるタイミングで、まったく異なるコンテキストで実行されることがわかります-dealloc。1 つには、ファイナライズは別のスレッドで行われるため、メソッド内の別のオブジェクトに安全に送信することはできません-removeObserver:forKeyPath:-finalize

と のメモリ (およびその他の希少なリソース) の管理に固執し-dealloc-finalize別の-invalidate方法を使用して、決定論的な時点でオブジェクトの処理が完了したことを所有者に伝えるようにします。そこでKVO観測を削除するなどのことを行います。コードの意図がより明確になり、対処する微妙なバグが少なくなります。

于 2008-08-18T00:33:13.943 に答える
5

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

于 2008-08-29T15:56:34.167 に答える
2

「-dealloc と -finalize でメモリ (およびその他の希少リソース) を管理することに固執する」という Chris のコメントに完全に同意します。多くの場合、dealloc 関数で NSTimer オブジェクトを無効にしようとする人を見かけます。問題は、NSTimer がそのターゲットを保持していることです。そのため、その NSTimer のターゲットが自分自身である場合、dealloc が呼び出されることはなく、潜在的に厄介なメモリ リークが発生する可能性があります。

で無効化し-invalidate、他のメモリ クリーンアップを実行しますdeallocfinalize.

于 2008-09-15T18:16:34.263 に答える