Search code examples
iosobjective-ccocoacore-datansmanagedobjectcontext

Primitive Setters and NSManagedObjectContext Notifications


When using primitive setters (e.g. setPrimitiveValue:forKey:)to change values of NSManagedObjects (or their subclasses), will these changes be included in the userInfo of NSManagedObjectContextObjectsDidChange notifications, or the objects be listed in the updatedObjects of NSManagedObjectContextDidSave notifications?

Subsequently, will values set by primitives be saved to disk? (assuming use of a sqlite persistent store)

I haven't been able to find any specific information on this, and I'd rather not make assumptions from my limited testing, or at least not without (attempting) a deeper understanding of it. Thanks!


Solution

  • Did some further testing with a small sample project to minimize other factors, and here are my findings:

    Saving is dependent on willChangeValue:forKey: notifications. As long as the NSManagedObject is KVC compliant for that key, this call will set the object's hasChanges flag to YES. When this happens, an object will be included in the next NSManagedObjectContextObjectsDidChange notification. The NSManagedObject itself knows exactly which values have changed though, regardless of what keys KVO notifications were posted for.

    E.g. even if key A is changed via the primitive setter, and a notification is posted for key B's change, the object will notice the change for key A.

    Similarly, NSManagedObjectContextDidSave will only save an object whose hasChanges is YES but again, the object knows of all changed values regardless of the notifications posted, and all changes will be saved to disk.

    I was surprised that didChangeValue:forKey: does not have any effect on saving behaviour. It is key to undo management though, which requires the standard wrapping of KVO calls around the primitive setter to function:

    [self willChangeValueForKey:@"key"];
    [self setPrimitiveValue:value forKey:@"key"];`
    [self didChangeValueForKey:@"key"];