KVO 和 ARC 如何移除Observer
Posted
技术标签:
【中文标题】KVO 和 ARC 如何移除Observer【英文标题】:KVO and ARC how to removeObserver 【发布时间】:2011-10-21 01:17:57 【问题描述】:如何从ARC 下的对象中删除观察者?我们是否只是添加观察者而忘记删除它?如果我们不再手动管理内存,我们该从哪里放弃观察?
例如,在视图控制器上:
[self.view addObserver:self
forKeyPath:@"self.frame"
options:NSKeyValueObservingOptionNew
context:nil];
以前,我会在视图控制器的dealloc
方法中调用removeObserver:
。
【问题讨论】:
请注意,对 KVO .frame 来说这是一个非常糟糕的主意。正如 Apple 工程师在 *** 上在其他地方所写的那样,UIKit 的 frame 属性不符合 KVO。当它起作用时,它只是纯属偶然。 您的 keyPath 不应该是@"frame"
而不是 @"self.frame"
?
【参考方案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 错误。这样做解决了这个问题。另外,来自***.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,接受那个人的回答!以上是关于KVO 和 ARC 如何移除Observer的主要内容,如果未能解决你的问题,请参考以下文章