Re: Core Data KVO with To-Many Relationships
Re: Core Data KVO with To-Many Relationships
- Subject: Re: Core Data KVO with To-Many Relationships
- From: Ben Trumbull <email@hidden>
- Date: Wed, 7 Oct 2009 23:33:39 -0700
Since my previous post, I have been able to get the functionality I
was hoping for with the following code in my "Department" subclass. I
would greatly appreciate some feedback as to whether this is an
appropriate way to implement the functionality or if there is a more
efficient or cleaner way.
KVO doesn't have an easy way to observe a collection's contents, so
the NSNotification approach is your best bet.
- (void)awakeFromFetch {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(managedObjectContextDidChange:) name:
NSManagedObjectContextObjectsDidChangeNotification object:[self
managedObjectContext]];
}
- (void)awakeFromInsert {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(managedObjectContextDidChange:) name:
NSManagedObjectContextObjectsDidChangeNotification object:[self
managedObjectContext]];
}
Most people use a 3rd object to do this instead of having the
individual managed objects. You can have an innocent bystander
observe the NSManagedObjectContextObjectsDidChangeNotification, see if
any interesting objects have changed, and then ping them to recompute
whatever you need. Much easier to manage registering and
unregistering observers.
- (void)managedObjectContextDidChange:(NSNotification *)notification {
// Get a set containing ALL objects which have been changed
NSSet *insertedObjects = [[notification userInfo]
objectForKey:NSInsertedObjectsKey];
NSSet *updatedObjects = [[notification userInfo]
objectForKey:NSUpdatedObjectsKey];
NSSet *deletedObjects = [[notification userInfo]
objectForKey:NSDeletedObjectsKey];
//this method of gathering changed objects is because the final set
was always null if the first set was null
NSSet *changedObjects;
if([insertedObjects count] > 0){
changedObjects = [insertedObjects
setByAddingObjectsFromSet:updatedObjects];
changedObjects = [changedObjects
setByAddingObjectsFromSet:deletedObjects];
}else{
if([updatedObjects count] > 0){
changedObjects = [updatedObjects
setByAddingObjectsFromSet:deletedObjects];
}else{
changedObjects = [NSSet setWithSet:deletedObjects];
}
}
if([changedObjects intersectsSet:[self employees]]){
//if an employee in this department changed, indicate
that the totalSalary attribute should be refreshed
[self willChangeValueForKey:@"totalSalary"];
[self didChangeValueForKey:@"totalSalary"];
}
}
That's the basic idea, but it's easier and faster to do that once, in
one master observer, than in each managed object.
- Ben
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden