On 14 Nov 2009, at 02:11, David Catmull wrote:

> In my Core Data app, I have objects with a date property, and I want to 
> maintain a list of all years that I have objects in. I'm having trouble 
> settling on an approach.
> 
> Currently, I'm listening for 
> NSManagedObjectContextObjectsDidChangeNotification. This is working fine for 
> additions and deletions, but it's harder for changes, mainly because I don't 
> know the old value. If I did, I could check if the old year still has any 
> other objects in it. As it is I have to refresh the whole list. I also get 
> more notifications than I need, since I only care about date changes on this 
> one entity.
You could cache the old year in a transient property and detect the change that 
way.

> 
> Another option is to use KVO so I can be notified only of date changes. I'm 
> assuming that registering as an observer for potentially thousands of Core 
> Data objects doesn't carry too much overhead. The down side is that if lots 
> of objects change at once, I get lots of individual callbacks, and I worry 
> that that would be a bottleneck.
> 
I find it hard to get a combination of KVO, bindings, CoreData and undo that 
works cleanly and efficiently.
I faced a perhaps similar situation and implemented a system of coalescing 
notifications.

My NSManagedObject subclass raises manual KVO notifications for use in bindings 
put each property modified also calls subclass method 
-postPropertyChangeNotification: (see below).
This sends a single notification for each modified keypath at the end of the 
runloop.
This means you get one notification regardless of how many changes there are.
So regardless of how many objects get their Year property modified you get one 
notification and can form your year list.

Another subclass method +keyPathsThatDoNotEnqueueCoalescingNotifications 
provides a way of overriding the coalescing for individual keypaths.

One point would be to consider if you want to support undo.
CoreData will undo your changes to your data model and post KVO notes but it 
won't access your model accessor's during undo.
Its possible to build a series of observations and notifications that works 
when doing, but fails when undoing.
So if you want undo support I would try to implement it now.

To get undo support to function so that the GUI was always in sync with the 
model i found it necessary to listen for 
NSManagedObjectContextObjectsDidChangeNotification as well.

/*
 
 post property change notification

 provides an alternative to observing all model properties
 
 */
- (void)postPropertyChangeNotification:(NSString *)keyPath
{       
        // build our notification
        NSDictionary *userInfo = [NSDictionary 
dictionaryWithObjectsAndKeys:keyPath, @"keyPath", nil];
        NSNotification *notification = [NSNotification 
notificationWithName:@"MGSUnitEntryUpdated" object:self userInfo:userInfo];
        
        // the default is that we shall coalesce these notifications
        NSUInteger coalesceMask = NSNotificationCoalescingOnName;
        
        // determine any keyPaths that require distinct notifications
        // eg: date as the receiver of the notification treats it differently 
to all other keypaths
        NSSet *nonCoalescingKeypaths = [[self class] 
keyPathsThatDoNotEnqueueCoalescingNotifications];
        if ([nonCoalescingKeypaths containsObject:keyPath]) {
                coalesceMask = NSNotificationNoCoalescing;
        }
        
        // enqueue the notification
        [[NSNotificationQueue defaultQueue] enqueueNotification:notification 
                                                                                
postingStyle:NSPostASAP         // run at end of runloop
                                                                                
coalesceMask:coalesceMask 
                                                                                
forModes:nil];
}

/*
 
 keypaths that do not enqueue coalescing notifications
 
 */
+ (NSSet *)keyPathsThatDoNotEnqueueCoalescingNotifications
{
        NSSet *keyPaths = [super 
keyPathsThatDoNotEnqueueCoalescingNotifications];
        
        // we require that separate uncoalesced notifications are sent for 
these property changes
    keyPaths = [keyPaths setByAddingObjectsFromSet: [NSSet setWithObjects: 
@"date", nil]];
        
    return keyPaths;
}


> Recommendations? Other options?
> 
> Thanks,
> 
> -- 
> David Catmull
> [email protected]
> http://www.uncommonplace.com/
> 
> _______________________________________________
> 
> Cocoa-dev mailing list ([email protected])
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/jonathan%40mugginsoft.com
> 
> This email sent to [email protected]

_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to