将KVO属性的对象作为观察者移除的最佳做法

我想知道什么是添加和删除自己作为一些KVO财产观察员的最佳做法。 我已经将我的控制器对象添加为UIView的“隐藏”属性的观察者。 我在我的视图控制器的loadView中添加了观察者。 现在,什么是DE注册为这个属性的观察员的最佳地点。 一旦视图控制器的视图被解除,我想停止观察。 有时候,我在控制台警告下面看到,有时候我会因观察员的移动而崩溃。

有什么build议么?

An instance 0x190659e0 of class UIView 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: 

广义而言,当您不再需要KVO时,您需要取消注册。 为了防止你看到的错误,你需要确保你已经取消注册观察对象被释放。

实际上,这意味着如果你不能控制它的生命周期,那么你真的不应该观察它。 你没有很强的参考。 如果你有一个强烈的参考,你需要取消注册之前,你的强烈的参考消失。 通常情况下,我处理这个问题的方式是处理旧值的注销,并在自定义设置器中为引用要观察的对象的(强)属性在新值上注册。 然后,在dealloc,我也取消了我的遵守。 像这样的东西:

 - (void)setSomeView:(NSView *)someView { if (someView != _someView) { [_someView removeObserver:self forKeyPath:@"someKey"]; _someView = someView; [_someView addObserver:self forKeyPath:@"someKey" options:0 context:NULL]; } } - (void)dealloc { [_someView removeObserver:self forKeyPath:@"someKey"]; } 

这样,我只观察到我拥有很强的(拥有)引用的对象,所以它们不能从我的下面被释放出来。 而且,当我被释放时,我也取消了注册的观察。

取决于你何时注册:

  • 如果你在注册中注册,将会出现
  • 如果你在viewDidLoad / loadView中注册 – 在dealloc中取消注册

当然有更多的select..这个想法是find'对手的方法',所以你注册和注销是平衡的

对于任何使用Swift 3.0的人来说,请看下面的代码,

 override function viewDidLoad() { super.viewDidLoad() // some code webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil) } deinit { webView.removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress)) } 

deinit在取消分配WKWebview工具包和更改navigationController之前删除观察者。

希望这可以帮助