35

weakスーパービュー (ビュー B) へのプロパティを持つビュー (このビュー A と呼びます) があります。ビュー A KVO のスーパービュー、ビュー B。ビュー A のビュー B への参照は弱いプロパティであるため (保持サイクルを防ぐため)、オブザーバー (A が B を観察している) を削除するにはどうすればよいですか? ビュー A のビュー B への参照は、削除する前にゼロになります。

View Controller は A への強力な参照を持っているため、A は B よりも長生きします。これはリーク ログ メッセージです。

An instance 0x9ac5200 of class UITableView was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
<NSKeyValueObservationInfo 0x8660360> (
<NSKeyValueObservance 0x8660320: Observer: 0x8660020, Key path: contentOffset, Options: <New: YES, Old: NO, Prior: NO> Context: 0x8660020, Property: 0x864ac80>
)

B は UITableView です。にブレークポイントを設定すると、NSKVODeallocateBreak役に立たない結果が生じます。

AremoveFromSuperviewでは、オブザーバーを削除しようとしましたが、A の B への参照は既にnilです。

切り替えてunsafe_unretained手動で行うか[A removeFromSuperview]、ビューコントローラーを呼び出すとdealloc、問題が解決します。weakプロパティを使用してこれを解決する方法を知りたいのですが。

関連するコードは次のとおりです: https://gist.github.com/2822776

4

3 に答える 3

2

削除は自動化できるため、このケースに特別に必要なコードは本当に不要だと思います。

ARC の導入により、Apple はこのようなケースを修正するオブザーバーの自動削除を提供する必要がありましたが、残念ながらそうではありませんでした。しかし、この不足している機能を追加する独自のカテゴリを作成しました: https://github.com/krzysztofzablocki/SFObservers ブログでそれをどのように管理したかを説明しました: http://www.merowing.info/2012/ 03/automatic-removal-of-nsnotificationcenter-or-kvo-observers/

私のソリューションを見ると、メソッドの1つが他のメソッドを呼び出しても、元のコードが呼び出されることが保証されるため、Appleが内部動作を変更しても、カテゴリは引き続き正常に機能することに気付くでしょう:)

于 2012-05-29T10:28:35.353 に答える
1

selfスーパービューを参照する明示的な弱いプロパティを定義し、次のようなキーパスで観察できます@"propertyReferringSuperview.propertyOfSuperview"か? KVO 通知を受け取ったらself.propertyReferringSuperview == nil、監視を停止するかどうかを確認し@"propertyReferringSuperview.propertyOfSuperview"ます。

于 2012-05-29T09:15:40.177 に答える
0

弱いプロパティを追加する代わりに、superviewプロパティを使用して実装willMoveToSuperview:し、KVO 観測を追加/削除することができます。

- (void)willMoveToSuperview:(UIView *)newSuperview {
    [self.superview removeObserver:self forKeyPath:@"contentOffset" context:context];
    [newSuperview addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:context];
    [super willMoveToSuperview:newSuperview]; // optional as default implementation does nothing
}
于 2012-05-29T10:33:06.953 に答える