addObserver:forKeyPath:options:context:
を使用してオブジェクトの値を監視する場合、最終的には後でクリーンアップするためにそのオブジェクトでremoveObserver:forKeyPath:
を呼び出します。それを行う前に、オブジェクトが実際にそのプロパティを監視しているかどうかを確認することは可能ですか?
私はコードで、オブジェクトが必要なときにのみオブザーバーを削除するようにしましたが、オブザーバーが自身を2回削除しようとする可能性がある場合があります。私はこれを防ぐために取り組んでいますが、念のために、自分のコードが実際に何かのオブザーバーであるかどうかを最初に確認する方法があるかどうかを把握しようとしています。
[...]オブジェクトが実際にそのプロパティを監視しているかどうかを確認できますか?
いいえ。KVOを扱うときは、常に次のモデルを念頭に置いてください。
観測を確立するとき、その正確な観測を削除する責任があります。観測はそのコンテキストによって識別されます。したがって、コンテキストは一意である必要があります。通知を受信するとき(およびLionでは、オブザーバーを削除するとき)、パスではなくコンテキストを常にテストする必要があります。
監視対象オブジェクトを処理するためのベストプラクティスは、監視対象オブジェクトのセッターで監視を削除して確立することです。
static int fooObservanceContext;
- (void)setFoo:(Foo *)foo
{
[_foo removeObserver:self forKeyPath:@"bar" context:&fooObservanceContext];
_foo = foo; // or whatever ownership handling is needed.
[foo addObserver:self forKeyPath:@"bar" options:0 context:&fooObservanceContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == &fooObservanceContext) {
// handle change
} else {
// not my observer callback
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)dealloc
{
self.foo = nil; // removes observer
}
KVOを使用する場合、オブザーバーとオブザーバの両方のオブジェクトが、オブザベーションが行われている限り生きていることを確認する必要があります。
オブザベーションを追加する場合、これと同じオブザベーションを1回だけ削除することのバランスを取る必要があります。 KVOを使用しているのはあなただけだと思い込まないでください。フレームワーククラスは、独自の目的でKVOを使用する場合があるため、コールバックのコンテキストを常に確認してください。
最後に指摘したいのは、監視対象のプロパティがKVOに準拠していることです。 何も観察することはできません 。
NSKeyValueObservingプロトコルの一部は次のとおりです。
- (void *)observationInfo
オブザーバーをリストする必要があります。
[〜#〜] edit [〜#〜]デバッグのみに役立ちます。
これは客観的な質問です。しかし、多くの人がSwift/objective-cを一緒に使用しているため、古いバージョンのKVOよりもSwift4の新しいAPIの利点を指摘したいと思いました。
KVOでaddObserver
を複数回実行すると、変更ごとに、自分がオブザーバーとして追加した現在の回数と同じ数のobserveValue
が取得されます。
removeObserver
を呼び出します。Swift4 observe
は、はるかにスマートで迅速です!
invalidate
のtoken
は1つで十分です。invalidat
オブザーバーを開始する前に実行するか、observe
を実行しても何度もクラッシュしませんしたがって、質問に具体的に答えるために、新しいSwift4 KVOを使用する場合は、気にする必要はありません。 invalidate
を呼び出すだけで大丈夫です。しかし、古いAPIを使用している場合は、ニコライの答えを参照してください