Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:
like image 346
Abhinav Avatar asked Feb 07 '14 23:02

Abhinav


People also ask

What is KVO key-value observation )?

KVO, which stands for Key-Value Observing, is one of the techniques for observing the program state changes available in Objective-C and Swift. The concept is simple: when we have an object with some instance variables, KVO allows other objects to establish surveillance on changes for any of those instance variables.

Can you explain KVO and how it's used on Apple's platforms?

Key-value observing is a Cocoa programming pattern you use to notify objects about changes to properties of other objects. It's useful for communicating changes between logically separated parts of your app—such as between models and views. You can only use key-value observing with classes that inherit from NSObject .

What is Key-value coding and Key-value observing?

KVO and KVC or Key-Value Observing and Key-Value Coding are mechanisms originally built and provided by Objective-C that allows us to locate and interact with the underlying properties of a class that inherits NSObject at runtime.


2 Answers

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.

like image 117
Andrew Madsen Avatar answered Sep 24 '22 06:09

Andrew Madsen


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

like image 38
Daij-Djan Avatar answered Sep 22 '22 06:09

Daij-Djan