你如何从弱势财产中删除KVO?

时间:2012-05-29 04:48:28

标签: objective-c ios macos automatic-ref-counting

我有一个视图(我们称之为视图A),其超级视图具有weak属性(视图B)。查看KVO的超视图,视图B.由于视图A对视图B的引用是弱属性(为了防止保留周期),如何移除观察者(A观察B)?在我有机会删除它之前,查看A对视图B的引用已经过了。

由于视图控制器具有对A的强引用,因此B比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设置断点会产生无用的结果。

在A的removeFromSuperview中,我尝试删除观察者,但A对B的引用已经是nil

切换到unsafe_unretained并手动执行更多操作或在视图控制器的[A removeFromSuperview]中调用dealloc可解决问题。我想知道如何使用weak属性来解决这个问题。

以下是相关代码:https://gist.github.com/2822776

3 个答案:

答案 0 :(得分:2)

我发现这种情况下特别需要的任何代码都是不必要的,因为删除可以自动化。

随着ARC的推出,Apple应该提供自动删除观察者,以便修复这样的案例,但不幸的是他们没有。但我已经制作了自己的类别,增加了这个缺乏功能:https://github.com/krzysztofzablocki/SFObservers 我已经解释了我在博客上的管理方式:http://www.merowing.info/2012/03/automatic-removal-of-nsnotificationcenter-or-kvo-observers/

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

答案 1 :(得分:1)

您可以定义引用超级视图的显式弱属性,然后使用self之类的关键路径观察@"propertyReferringSuperview.propertyOfSuperview"?收到KVO通知后,您会检查self.propertyReferringSuperview == nil是否停止观察@"propertyReferringSuperview.propertyOfSuperview"

答案 2 :(得分: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
}