21
votes

I have a custom NSManagedObject subclass, say, Person. I also have a UIView registered with -addObserver:forKeyPath:options:context: to observe various properties of a Person, some of which are persistent like "name" and others are just dumb KVO-compliant accessors unrelated to Core Data, like "drinking".

@interface Person : NSManagedObject
{
    BOOL drinking;
}
@property (nonatomic, retain) NSString* name;
@property (nonatomic, readonly) BOOL drinking;
@end

@implementation Person
@dynamic name;
...
- (void) getDrunk {
    [self willChangeValueForKey: @"drinking"];
    drinking = YES;
    [self didChangeValueForKey: @"drinking"];
}
...
@end

Everything works. Whenever I send -getDrunk or set the name property, the view does get notified. I'm a happy man except when I read NSManagedObject docs which state:

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key

Fact 1. YES if the receiver provides automatic support for key-value observing change notifications for key, otherwise NO.

Fact 2. The default implementation for NSManagedObject returns NO for modeled properties, and YES for unmodeled properties.

Now I'm trying hard to parse the above two facts from the docs. Checking Fact 2 is easy and class Person indeed returns NO for @"name" and YES for @"drinking". But then, how does the view get notified when the name changes? KVO docs clearly say,

Using automatic observer notifications, it is not necessary to bracket changes to a property with invocations of willChangeValueForKey: and didChangeValueForKey: when mutating properties via key-value coding and key-value coding compliant methods.

So, if Person returns NO from +automaticallyNotifiesObserversForKey: for @"name", it would seem that I have to manually wrap the name setter in will/didChangeValueForKey: for KVO to work. However, KVO works just fine. What am I missing? What's the point in NSManagedObject's overriding +automaticallyNotifiesObserversForKey: and documenting it if does not seem to change standard KVO behaviour?

Please, help me regain my sanity.

2

2 Answers

20
votes

Well, NSManagedObject does provide an implementation for the name property (as well as the - name and - setName: methods). I would assume that the implementations provided by Core Data do include calls to willChangeValueForKey: and didChangeValueForKey:.

So, although the KVO is "automatic" in the sense that you didn't have to do anything to make it work, I would imagine that it is not automatic in the sense that willChangeValueForKey: and didChangeValueForKey: are being called by the methods in NSManagedObject that provide the dynamic property implementations.

0
votes

I also have a UIView registered with -addObserver:forKeyPath:options:context

It is the job of the controller to take the data from the model and set it on the view, and formatting it along the way. The view should be able to display data from any model not just a Person - think title, subtitle rather than name. Also the controller can receive edits from the view and apply them to the model as well as filtering notifications from the model to prevent things being needlessly set back on the view again where they just came from.