views:

322

answers:

3

In Cocoa, addObserver:forKeyPath:options:context: retains "neither the receiver, nor anObserver". Therefore I assume observing self is allowed; that is, it's perfectly valid to do something like

[self addObserver:self forKeyPath...]

As long as you remember to unregister self as an observer as the first thing in dealloc.

Is this assumption correct?

+4  A: 

Yes, there is not really any reason you can't observe self. But like you said, like any KVO observation, make sure to remove yourself as an observer before being dealloced.

For the record, one alternate way of doing this if you're just talking about a simple key is to write a custom setter and execute whatever code you need in the setter. This style makes it a little more obvious what the full effects of calling the setter are. The KVO way is a bit more flexible though, and works with key paths that contain multiple components.

Brian Webster
+1  A: 

I do what Brian Webster said. Here's an example:

//.h
...
@property(readwrite, retain, setter=setMyPropertySynth:) id myProperty;
-(void)setMyProperty:(id)newValue;
....


//.m
...
@synthesize myProperty;

-(void)setMyProperty:(id)newValue
{
    //add code here

    [self setMyPropertySynth:newValue];

    //add more code here
}
...
Benedict Cohen
+1  A: 

Don't remove an observer in -dealloc. Why? Because when you turn on the garbage collector things will stop working; -dealloc never gets called. You should just use the -dealloc and -finalize methods for memory-related cleanup code.

Graham Lee
Good point; but, what do I use instead then?
Adam Ernst
Just set it up as part of the object's lifecycle. If the thing that creates it tells it what to observe, and when to stop observing it, you're _injecting dependencies_ which makes your object easier to re-use and to test.
Graham Lee
...but much easier to use incorrectly, and undermines Cocoa memory management. If every creator must also know that the created object must observer such-and-such (particularly if that's itself), we've moved private information into the caller, which is bad. Worse, if I need a "destroy you now" method that undoes this observation, then the whole point of GC went out the window. The best solution we have is to duplicate the non-memory management pieces into dealloc and finalize (possibly hoisting to a shared routine). This include NSNotificationCenter removeObserver as well.
Rob Napier