Properly handle the deletion of an object only if there are no relationships?
I have a Person
entity which belongs to a Department
in a one to many relationship.
I would like to be able to delete the Department
when there are no more Person
s associated with it (either through the deletion of the Person
entity, or a change to the Person
's department
attribute). Right now, I'm trying to do so with the following handler for NSManagedObjectContextObjectsDidChangeNotification
(Currently just trying to see deletions, and delete appropriately):
- (void)managedObjectDidChange:(NSNotification *)notification {
NSSet *updatedObjects = [[notification userInfo] objectForKey:NSDeletedObjectsKey];
for (NSManagedObject *obj in updatedObjects) {
if ([obj.entity.name isEqualToString:@"Person"]) {
NSLog(@"Person Changed");
NSManagedObject *department = [(Person *)obj department];
NSLog(@"%i", [[department valueForKey:@"person"] count]);
开发者_如何学Python if ([[department] valueForKey:@"person"] count] == 0) {
NSLog(@"Department has no more people associated with it");
// deletion code
}
}
}
}
However, the count of the number of people associated with the department doesn't change when I delete a person. I am not performing a fetch on the Department
entity. Is that something I should be doing?
Easiest way: implement willSave
in your Department entity class (You are giving each entity its own class, right? *), have your department check itself for [self isDeleted] == NO
and [[self person] count] == 0
, and delete itself if so. (The check of isDeleted
isn't optional, because an entity changing itself inside willSave
triggers another call to willSave. The docs for NSManagedObject willSave
have more info.) This postpones the delete until the context is flushed back to disk, which shouldn't be a huge problem.
If you do need the Department to delete itself the instant the last person leaves it, have your Department entity observe itself with KVO. Register it as an observer on its own "person" property in awakeFromFetch
and awakeFromInsert
, and unregister in willTurnIntoFault
. When the person property changes, check it for empty. This is more work, so only try it if the first way doesn't work for you.
Finally, remember that the Person->Department relationship delete rule needs to be set to 'nullify' (when Person is deleted, it is removed from Department's persons), not 'no action' (when Person is deleted, you take responsibility for cleaning up the Department yourself) or 'cascade' (when any Person is deleted, its Department is deleted too!)
(* MOGenerator is a very nice helper for maintaining per-entity classes. http://rentzsch.github.com/mogenerator/ )
In your Person
subclass, override prepareForDeletion
. If the Department
has only one person
left, delete the Department
too. Apple's documentation even suggests using prepareForDeletion
as the best place to do custom delete propagation.
- (void)prepareForDeletion
{
[super prepareForDeletion];
if (self.department.persons.count == 1) {
[self.managedObjectContext deleteObject:self.department];
}
}
精彩评论