删除对象作为某些KVO属性的观察者的最佳实践

时间:2014-02-07 23:33:14

标签: ios objective-c cocoa-touch uiview key-value-observing

我想知道为某些KVO属性添加和删除self作为观察者的最佳做法是什么。我已将控制器对象添加为UIView的“隐藏”属性的观察者。我在视图控制器的loadView中添加了观察者。现在,DE注册为此属性的观察者的最佳位置是什么。我想在视图控制器的视图被取消后立即停止观察。有时我看到控制台警告下面,有时我因为观察员过度移除而崩溃。

有什么建议吗?

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:

4 个答案:

答案 0 :(得分:13)

从广义上讲,当您不再需要时,您需要取消注册KVO观察。为了防止您看到的错误,您需要确保在取消分配被观察对象之前取消注册。

实际上,这意味着如果您对其生命周期没有任何控制,那么您真的不应该观察到某些事情。你没有强烈的参考。如果您确实有强烈的引用,则需要在强引用消失之前取消注册。通常,我处理此问题的方法是处理旧值的取消注册,并在自定义setter中的新值上注册(强)属性,引用要观察的对象。然后,在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"];
}

这样,我只观察到我有强烈(拥有)引用的对象,所以它们不能从我下面解除分配。并且,当取消分配时,我也会取消注册观察。

答案 1 :(得分:4)

取决于您何时注册:

  • 如果您在viewWilllAppear中注册 - 在viewWillDisappear中取消注册
  • 如果您在viewDidLoad / loadView中注册 - 在dealloc中取消注册

当然有更多的选择..想法是找到'对应的方法'所以你注册&注销是平衡的

答案 2 :(得分:0)

对于使用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))
    }

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

希望这有帮助

答案 3 :(得分:0)

快捷键4

var observer: NSKeyValueObservation?

self.observer = myPlayer.observe(\.rate, options:  [.new, .old], changeHandler: { (player, change) in
     if player.rate == 1  {
          print("Playing")
      }else{
           print("Stop")
      }
 })

 // Later You Can Remove Observer      
 self.observer?.invalidate()