开发者

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 Persons 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];
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜