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

Ios 作为某些KVO属性的观察者删除对象的最佳实践,ios,objective-c,cocoa-touch,uiview,key-value-observing,Ios,Objective C,Cocoa Touch,Uiview,Key Value Observing,我想知道添加和删除某些KVO属性的self-as-observer的最佳实践是什么。我已将控制器对象添加为UIView的“隐藏”属性的观察者。我在视图控制器的loadView中添加了观察者。现在,什么地方是取消注册为该属性的观察者的最佳位置。我想在视图控制器的视图被关闭后立即停止观察。有时我会看到以下控制台警告,有时我会因为作为观察者的过度移除而崩溃 有什么建议吗 An instance 0x190659e0 of class UIView was deallocated while key v

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

有什么建议吗

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:

取决于您注册的时间:

  • 如果在ViewWillAppear中注册-在ViewWillAppear中取消注册将消失
  • 如果在viewDidLoad/loadView中注册-在dealloc中注销

当然还有更多的选择。。我们的想法是找到“对等方法”,这样您的注册和取消注册是平衡的

从广义上讲,当您不再需要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"];
}

这样,我只观察我有一个强(拥有)引用的对象,所以它们不能从我下面释放出来。而且,当我被解除分配时,我也会取消注册以进行观察。

对于任何使用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之前,Denit将删除观察者


希望这有帮助

Swift 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()

在ios5下,您必须注意以下几点