【问题标题】:KVO and ARC how to removeObserverKVO 和 ARC 如何移除Observer
【发布时间】:2011-10-21 01:17:57
【问题描述】:

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

例如,在视图控制器上:

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

以前,我会在视图控制器的dealloc 方法中调用removeObserver:

【问题讨论】:

  • 请注意,对 KVO .frame 来说这是一个非常糟糕的主意。正如 Apple 工程师在 StackOverflow 上在其他地方所写的那样,UIKit 的 frame 属性不符合 KVO。当它起作用时,它只是纯属偶然。
  • 您的 keyPath 不应该是 @"frame" 而不是 @"self.frame"

标签: ios cocoa-touch key-value-observing automatic-ref-counting


【解决方案1】:

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

如果您之前覆盖了-release,那么您的做法是错误的。

【讨论】:

  • 你确定吗?我引用clang.llvm.org/docs/…,第 7.1.2 节。 dealloc:“基本原理:即使 ARC 自动销毁实例变量,仍然有正当理由编写 dealloc 方法,例如释放不可保留的资源。在这种方法中调用 [super dealloc] 失败几乎总是一个错误。”
  • @ElisevanLooij 是的,这是真的。如果你从这个类派生,很明显你必须调用[super dealloc]。还有谁应该为你做这件事。
  • @ElisevanLooij 糟糕,之前应该检查过。不允许在 dealloc 方法中调用[super dealloc]。不知道在子类化提到的类时这将如何工作。也许建议改用finalize(你打电话给[super finalize]
  • @ElisevanLooij - 他们试图说明的重点是手动内存管理案例。因为在该方法中不最后调用[super dealloc] 几乎总是手动内存管理下的错误,编译器现在为您处理它,这就是您不能再直接调用-dealloc 的原因。您在 ARC 下的 -dealloc 方法中放入的唯一内容是您需要释放的任何非对象资源,或清理任务(如删除观察者)。他们使用的措辞有点含糊,但这就是他们的意思。
  • @BjörnMilcke - 当我评论 Elise 的回答时,-finalize 用于垃圾收集下,其中-dealloc 从未被调用,但将此代码放在-dealloc 下是完全可以接受的弧。 [super dealloc] 会自动为您调用,这就是为什么在 ARC 下调用它是错误的。
【解决方案2】:

我用这段代码来做

- (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
}
}    

【讨论】:

  • dealloc 中的异常处理有什么意义?对此采取任何行动都为时已晚。
  • 在 dealloc 中删除实例变量上的观察者有什么意义?这个 uAvatarImage 很快就会连同它订阅了它的关键路径的所有观察者一起被释放。
  • @shoumikhin 我正在使用 ARC,我不得不在 dealloc 方法中删除观察者。我和你有同样的问题。但是,当我运行该类的多个实例时,最终我得到了 exc_bad_address 错误。这样做解决了这个问题。另外,来自stackoverflow.com/questions/32490808/… 的答案帮助我发现了问题。
【解决方案3】:

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

【讨论】:

  • 请注意,他指的是那里的垃圾收集,而不是 ARC(他的答案写于 2008 年)。在垃圾回收下,-dealloc 永远不会被调用。在 ARC 中,它是。在-dealloc 中删除 KVO 观察者是完全可以接受的,正如 Chris Lattner(他知道他在说什么)在 Apple 的开发者论坛中指出的那样:devforums.apple.com/message/475850
  • 感谢布拉德,感谢您完成所有这些工作。不最终确定,是的释放,但没有[超级释放]。真的很简单,一旦你知道了。嘿,@drunknbass,接受那个人的回答!
猜你喜欢
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
相关资源
最近更新 更多