Very difficult to be informed of changes to Core Data Managed Objects

Originator:jerry
Number:rdar://6624874 Date Originated:20090226
Status:open Resolved:
Product:Mac OS X Product Version:10.5
Classification:enhancement Reproducible:always
 
Summary:  In many applications, auxiliary views or objects are interested in changes that occur to Core Data managed objects.  In Cocoa, such information is ordinarily obtained by notifications or key-value observing (KVO).  But using either method to obtain information about managed objects is incomplete or difficult.

Steps to Reproduce:
Build an Core Data application such as Apple's DepartmentAndEmployees sample project.  Add some auxiliary views or objects which would like to be informed of changes to some of the managed objects.  For example,
a) An OrgChart view wants to be informed whenever the directReports of any Employee changes.
b) A Payroll object is interested wants to be informed whenever the 'salary' of any Employee changes, or an Employee is added or deleted.
c) A DuplicateFirstNames object wants to be informed whenever the firstName of an Employee changes, or an Employee is added or deleted.

Expected Results:
There should be an easy way to register for notifications or use KVO to be informed of the desired changes.

Actual Results:
There appear to be three solutions available to get the desired information, but none of them are very practical.

Solution 1.  Use KVO.  Although adding observers can be done rather systematically, in awakeFromInsert and awakeFromFetch, removing observers must be done (1) when deallocating the moc and (2) in the managed object's -dealloc method (which is not recommended for subclassing).  The latter is to catch objects still on the undo stack or elsewhere, and requires checking that the observer has not already been removed by the former.  Removing the observers when deallocating the moc is also an ugly process -- you fetch all objects and send them a special "-removeYourObservers" message, if they respond.  Another alternative considered is to remove the observer in -didTurnIntoFault, but this is not acceptable because -didTurnIntoFault may be invoked when an object is deleted, but if delete is reversed by Undo, and faulted back in, there is no hook available (i.e. -didUnturnIntoFault) for the programmer to know that the object is back so the observer can be restored.

Solution 2.  Use Custom Setters.  For each key/value in each object that is to be observed, implement a custom setter, and in each such custom setter post a notification of the value change.  This is not too bad with attributes, because there is only one setter per attribute.  But for to-many relations you need to override the four (or is it five) set mutator methods in order to cover all the possible ways in which the relationship may be changed.  What if more mutator methods are added in some future version of Mac OS?  This requires much code and seems quite fragile.

Solution 3.  Use NSManagedObjectContextObjectsDidChangeNotification.  Interested objects can register for NSManagedObjectContextObjectsDidChangeNotification.  The information you get in the notification is adequate if objects are added or deleted, but not for updated objects because it does not tell you the key of the value which changed that caused the notification.  You can send -changedValues to the object, but this will return ^all^ key/values that were changed since the last time the managed object context was saved.  So you either need to have some kind of memory to filter out the repititions, or process the same change multiple times.  The former is a kludge, and may be too expensive, and the latter may be unacceptable, for example, if the user is to be alerted when a change occurs.

Notes:
My favored solution might be to enhance NSManagedObjectContextObjectsDidChangeNotification so that it included the key/value immediately responsible for the change.  Then, only one notification needs to be registered for, and only one method needs to be written, the selector for this notification, in which the programmer would filter out whatever changes are relevant and forward appropriate messages to the interested objects or views.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!