KVOとARCでObserverを削除する方法


87

ARCの下のオブジェクトからオブザーバーをどのように削除しますか?オブザーバーを追加するだけで、削除するのを忘れますか?手動でメモリを管理しなくなった場合、どこで監視をやめますか?

たとえば、ViewControllerでは次のようになります。

[self.view addObserver:self
            forKeyPath:@"self.frame"
               options:NSKeyValueObservingOptionNew 
               context:nil];

以前は、removeObserver:ViewControllerのdeallocメソッドを呼び出していました。


4
KVO.frameにとっては非常に悪い考えであることに注意してください。StackOverflowでAppleのエンジニアが他の場所で書いたように、UIKitのフレームプロパティはKVOに準拠していません。それが機能するとき、それは純粋な偶然によってのみです。
steipete 2011

2
keyPathはで@"frame"はなくすべきではありません@"self.frame"か?
besi 2012

回答:


126

-deallocキー値の観測を削除するのに適切な場所であると思われるARCで実装することもできます。[super dealloc]このメソッド内から呼び出す必要はもうありません。

-release以前にオーバーライドしていた場合は、間違った方法で処理を行っていました。


1
あなたはこれについて確信を持っていますか?clang.llvm.org/docs/…のセクション7.1.2から引用します。Dealloc:「理由:ARCはインスタンス変数を自動的に破棄しますが、保持できないリソースを解放するなど、deallocメソッドを作成する正当な理由があります。そのようなメソッドで[superdealloc]を呼び出さないことは、ほとんどの場合バグです。」
Elise van Looij 2011年

@ElisevanLooijはい、そうです。このクラスから派生した場合は、を呼び出す必要があることは明らかです[super dealloc]。他に誰があなたのためにこれをすべきか。
ビョルンランドメッサー2011

@ElisevanLooijおっと、まあ、前にチェックする必要があります。[super dealloc]Deallocメソッドで呼び出すことは許可されていません。言及されたクラスをサブクラス化するときに、これがどのように機能するかはわかりません。多分使用するだけのことをお勧めしますfinalize(お電話の場所の代わりに[super finalize]
ビョルンLandmesser

17
@ ElisevanLooij-彼らがそこにしようとしていたポイントは、手動のメモリ管理の場合に関するものです。[super dealloc]そのメソッドで最後に呼び出さないことは、ほとんどの場合、手動のメモリ管理ではバグであるため、コンパイラがそれを処理します。これが、-dealloc直接呼び出すことができなくなった理由です。-deallocARCの下のメソッドに入れるのは、解放する必要のある非オブジェクトリソース、またはオブザーバーの削除などのクリーンアップタスクだけです。彼らが使用する言葉遣いは少し泥だらけですが、これは彼らが意味したことです。
BradLarson

7
@BjörnMilcke-エリーゼの答えにコメントしているように-finalize、これはガベージコレクションの下で使用さ-deallocれ、呼び出されることはありませんが、このコードを-deallocARCの下に配置することはまったく問題ありません。 [super dealloc]は自動的に呼び出されます。そのため、ARCで呼び出すのはエラーです。
BradLarson

1

私はこのコードでそれをします

- (void)dealloc
{
@try{
    [self.uAvatarImage removeObserver:self forKeyPath:@"image" context:nil];
} @catch(id anException) {
    //do nothing, obviously it wasn't attached because an exception was thrown
}
}    

2
の例外処理のポイントは何deallocですか?それについて何もするのは遅すぎます。
Abizern 2014年

Deallocのインスタンス変数のオブザーバーを削除する意味は何ですか?このuAvatarImageは、キーパスにサブスクライブしているオブザーバーとともにすぐに割り当てが解除されます。
shoumikhin 2016

1
@shoumikhin ARCを使用しているので、deallocメソッドでオブザーバーを削除する必要がありました。私はあなたが持っているのと同じ質問があります。ただし、クラスの複数のインスタンスを実行すると、最終的にexc_bad_addressエラーが発生しました。これを行うと問題が解決しました。また、ここからの回答stackoverflow.com/questions/32490808/…は私が問題を発見するのに役立ちました。
mac10688 2016年

-2

スタックオーバーフローの他の場所では、Chris Hansonは、この目的でfinalizeメソッドを使用し、別のinvalidateメソッドを実装して、所有者がオブジェクトに完了したことを通知できるようにすることをお勧めします。過去に、ハンソンのソリューションはよく考えられていることがわかったので、それを使用します。


13
彼はARCではなくガベージコレクションについて言及していたことに注意してください(彼の回答は2008年に書かれました)。ガベージコレクションで-deallocは、呼び出されることはありません。ARCではそうです。それはでKVOのオブザーバーを削除するために完全に受け入れます-dealloc:ここで、Appleの開発者向けフォーラムで示し(何彼が話して知っている)クリス・ラットナーとして、devforums.apple.com/message/475850
ブラッド・ラーソン

3
このすべての作業を行ってくれたBradに感謝します。ファイナライズするのはいいえ、deallocははい、ただし[superdealloc]はありません。あなたがそれを知ったら、本当に簡単です。ねえ、@ drunknbass、その男の答えを受け入れてください!
Elise van Looij 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.