Best practice to remove an object as observer for some KVO property

I wanted to know what are the best practices for adding and removing self as observer for some KVO property. I have added my controller object as observer for “hidden” property of a UIView. I added the observer in loadView of my view controller. Now, what is the best place to DE-register as observer for this property. I want to stop observing as soon as the view controller’s view is dismissed. At times I am seeing below console warnings and at times I am crashing due to over removal as observer.

Any suggestions?

  • React Native iOS Native View send event with proper reactTag
  • Implementing touch-based rotation in cocoa touch
  • How to set content size of UIScrollView dynamically
  • Rotating a view in layoutSubviews
  • Using transparent background color in UIView by HTML code
  • A UIButton in my subview won't work
  • 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:
    

    3 Solutions Collect From Internet About “Best practice to remove an object as observer for some KVO property”

    In broad terms, you need to unregister for the KVO observation when you don’t need it anymore. To prevent the error you’re seeing, you need to be sure you’ve unregistered before the observed object is deallocated.

    In practical terms, that means that you really shouldn’t observe something if you don’t have any control over its lifecycle ie. you don’t have a strong reference to it. If you do have a strong reference to it, you need to unregister before your strong reference goes away. Typically the way I handle this is to handle unregisteration on an old value and registration on the new value in a custom setter for a (strong) property referring to the object to be observed. Then, in dealloc, I also unregister my observance. Something like this:

    - (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"];
    }
    

    That way, I only observe objects that I have a strong (owning) reference to, so they can’t be deallocated out from under me. And, when I’m deallocated, I also unregister for the observation.

    depends on when you register for it:

    • if you register in viewWilllAppear – unregister in viewWillDisappear
    • if you register in viewDidLoad / loadView – unregister in dealloc

    of course there are way more options.. the idea is to find the ‘counterpart method’ so you registers & deregisters are balanced

    For anyone who is questioning this with Swift 3.0, please see the below code which has just helped me:

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

    The deinit removes the observer before deallocating the WKWebview kit and changing the navigationController.

    Hope this helps