KVO和ARC如何删除


87

如何从ARC下的对象中删除观察者?我们只是添加观察者而忘记删除它吗?如果我们不再手动管理内存,该从何处辞职?

例如,在视图控制器上:

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

以前,我将调用removeObserver:视图控制器的dealloc方法。


4
请注意,这对于KVO .frame是一个非常糟糕的主意。正如Apple工程师在StackOverflow上其他地方所写的那样,UIKit的frame属性不符合KVO。当它起作用时,只有偶然的机会。
steipete 2011年

2
您的keyPath应该@"frame"不是@"self.frame"吗?
Besi 2012年

Answers:


126

您仍然可以-dealloc在ARC下实施,它似乎是删除对键值的观察的适当位置。您只是不再[super dealloc]从此方法中调用。

如果您-release之前是压倒一切,那么您是在以错误的方式做事。


1
你确定吗?我引用clang.llvm.org/docs/…中的7.1.2节。dealloc:“理据:即使ARC自动销毁实例变量,仍然有合理的理由编写dealloc方法,例如释放不可保留的资源。在这种方法中无法调用[super dealloc]几乎总是一个错误。”
Elise van Looij 2011年

@ElisevanLooij是的,是的。如果您从此类派生,似乎必须调用[super dealloc]。还有谁应该为您这样做。
比约恩Landmesser

@ElisevanLooij糟糕,应该在之前检查一下。不允许调用[super dealloc]dealloc方法。当将所提到的类子类化时,不知道这将如何工作。也许这只是建议使用finalize,而不是(你叫[super finalize]
比约恩Landmesser

17
@ElisevanLooij-他们试图提出的要点是关于手动内存管理的情况。因为[super dealloc]在该方法中不最后调用通常是手动内存管理下的一个错误,所以编译器现在为您处理它,这就是为什么您不能-dealloc直接调用了。放在-deallocARC下的方法中的唯一事情是释放或清理任务(例如删除观察者)所需的任何非对象资源。他们使用的措词有点混乱,但这就是他们的意思。
布拉德·拉尔森

7
@BjörnMilcke-正如我对Elise的回答所评论的那样,-finalize在垃圾回收下使用了此方法,-dealloc从未调用过此方法,但是将代码放在-deallocARC下是完全可以接受的。 [super dealloc]会自动为您调用,这就是为什么在ARC下调用它会出错。
布拉德·拉尔森

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什么?现在做任何事情都为时已晚。
阿比森2014年

在dealloc中删除实例变量的观察者有什么意义?此uAvatarImage会与已订阅其关键路径的所有观察者一起尽快释放。
shoumikhin

1
@shoumikhin我正在使用ARC,必须在dealloc方法中删除观察者。我有同样的问题。但是,当我运行该类的多个实例时,最终出现了exc_bad_address错误。这样做解决了问题。另外,来自这里stackoverflow.com/questions/32490808/…的答案帮助我发现了问题。
mac10688 '16

-2

堆栈溢出的其他地方,Chris Hanson建议为此使用finalize方法并实现一个单独的invalidate方法,以便所有者可以告诉对象它们已经完成。过去,我发现Hanson的解决方案是经过深思熟虑的,因此我将继续讨论。


13
请注意,他指的是那里的垃圾收集,而不是ARC(他的回答写于2008年)。在垃圾回收下,-dealloc永远不会被调用。在ARC中。-dealloc正如Chris Lattner(知道他在说什么)在Apple开发人员论坛中指出的那样,删除KVO观察员是完全可以接受的:devforums.apple.com/message/475850
Brad Larson

3
感谢Brad所做的所有工作。否最终确定,是否取消分配,但没有[super dealloc]。一旦知道就很简单。嘿,@ drunknbass,接受那个男人的回答!
Elise van Looij 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.