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.