2
votes

I have a class (call it classA) that contains a property named info (a model class, containing lots of info), wich in turn contains a property named name (a string). I want another class (classB) to receive a KVO notification when the string name changes in classA.

This is what I'm doing now on classB:

[classA addObserver: self forKeyPath: @"info.name" options: 0 context: nil];

There are two ways the value name changes on classA: when it is set directly like classA.info.name = ... and when info is set like classA.info = ...

When name is changed directly KVO works perfectly. However, when the info property is set and name changes indirectly, I get this error:

Cannot update for observer <classB> for the key path "info.name" from <classA>, most likely because the value for the key "info" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the classA class.

What should I change on classA to make this work?

2
Did you implement this model class and if so do you call willChangeValueForKey: before and didChangeValueForKey: after changing a property?trojanfoe
@trojanfoe name is set directly by a view-based tableview, using bindings, so there I can't do anything. info is set by me, and I'm not doing that. I've tried what you said just now and it still doesn't work. Same error. Oh, and by the way, I created this model class (classA)Alex
Show the code you are using to update the name property.trojanfoe
@trojanfoe name is bound to a textfield in a tableview. Perhaps you mean the code to change the info property? Here: [classA setInfo: newInfo] It's kinda what you'd expect.Alex
And you call will/didChangeValueForKey:@"info.name" before and after that?trojanfoe

2 Answers

4
votes

The cause of this issue comes from the fact that you are implementing the setter -setInfo: for info and calling willChangeValueForKey: | didChangeValueForKey: inside it.

I've seen many instances in which it is believed that the will|didChange... calls need to be implemented for the KVO notification to be fired. This is true only when the setter is not explicitly called. When you do call the setter, the KVO mechanism takes care of firing the notification.

Most of the times leaving these calls in the setter is harmless and just causes extra notifications, but as seen in this case, it does cause a problem when updating a keypath -- as opposed to a key.

In short, if you do implement a setter, do not call will|didChangeValueForKey: inside of it.

-1
votes

Options cannot be 0, I think.

Its an old API, back before Apple got diligent about API design, and you have to give it something.