35

我有一个视图(我们称之为视图 A),它具有weak其父视图(视图 B)的属性。视图 A KVO 的超级视图,视图 B。由于视图 A 对视图 B 的引用是一个弱属性(以防止保留循环),我怎样才能删除观察者(A 观察 B)?在我有机会删除它之前,视图 A 对视图 B 的引用将被取消。

A 比 B 寿命长,因为视图控制器对 A 有很强的引用。这是泄漏的日志消息:

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产生无用的结果。

在 A'sremoveFromSuperview中,我尝试删除观察者,但 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/自动移除-nsnotificationcenter-or-kvo-observers/

如果您查看我的解决方案,您会注意到,它确保调用原始代码,即使其中一种方法调用其他方法,所以即使苹果更改其内部行为,该类别仍然可以正常工作:)

于 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 回答