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?

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:

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.

Registering for Key-Value Observing, Registering as an Observer · Options · Context · Receiving Notification of a Change · Removing an Object as an Observer · KVO Compliance. This is a follow-up issue for #48 for discussions and actual implementation of automatic removal of any observation registered via KVOController when the observed objects are not retained in any way.

Using Key-Value Observing in Swift, Notify objects about changes to the properties of other objects. Mark properties that you want to observe through key-value observing with both the @objc  observer: The object to register for KVO notifications. The observer must implement the key-value observing method observeValueForKeyPath:ofObject:change:context:. key Path: The key path, relative to the receiver, of the property to observe. This value must not be nil.

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

Key-Value Observing, observer : The object to register for KVO notifications. The observer keyPath : The key path, relative to the receiver, of the property to observe. So there you have it: some general observations and best practices for KVO. Introduction to Key-Value Observing Programming Guide Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects. Important: In order to understand key-value observing, you must first understand key-value coding .

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

Hands-On Design Patterns with Swift: Master Swift best practices , Master Swift best practices to build modular applications for mobile, desktop, and eye out for the following issues: Always remember to remove observers properly, Not all properties in Objective-C objects support KVO—for example, it's not  If a computed property is not in use by some reaction (autorun, observer etc), computed expressions will be evaluated lazily; each time their value is requested (so they just act as normal property). Computed values will only track their dependencies if they are observed.

Exploring KVO alternatives with Swift, This post explores the pros and cons of KVO versus a couple of Swift alternatives. Swift – if something feels overly difficult, there probably is a better way. need to add the @objc keyword, which has some unpleasant side-effects, The ability to observe changes to an object's properties is a fantastic tool  Normally this issue happens when the registered observer deallocates and a KVO event triggers after that. For fixing you need to remove all observers before your object is going to be deallocated. In your case, you registered for 4 KVO changes and removing only 3. The following KVO observer is not removed anywhere and it is causing the issue.

Observers in Swift, We'll start by taking a look at two such observation techniques this very common to want to add some way for certain objects to be observed. class AudioPlayer { private var state = State.idle { // We add a property observer on '​state', earlier, you need to manually // remove the observer from the center. KVO, on the other hand, allows external objects to be notified of changes to another object's properties. E.g., a window controller could observe changes to a model's title property, and change the window title bar accordingly.

KVO and Data Binding in iOS Made Simple – RPLabs – Rightpoint , An object first registers to observe a property of another object. KVO is limited to observing key paths of objects, so it should be used in these layers in sync where chained delegates would be impractical at best. You have a formComplete property that depends on several other model properties. In KVO , an object can register itself for notifications when a property of itself or some other object changes. A property can be of two types. An attribute (name, title, age, salary etc) Relationship to other objects; KVO uses Key Value Coding mechanism for indirectly accessing an object’s attributes and relationships using string identifiers. Following are the steps that needs to be followed for Key-Value Observing Use the following method for adding an object as an observer for a keyPath

Comments
  • under ios5- there is viewDidUnload you have to be aware of