Check out "delete propagation". It's there to solve exactly that problem.
If that doesn't do exactly what you want / need: You can override - (void)prepareForDeletion
on the Book entity and at that point check for any Authors that are registered with the context and have pending changes (since their inverse will have changed) and have no books:
{
// ...
[[NSNotificationCenter defaultNotificationCenter] addObserver:self selector:@selector(deleteOrphanedAuthors:) name:NSManagedObjectContext object:moc];
// ...
}
- (void)deleteOrphanedAuthors:(NSNotification *)note;
{
NSManagedObjectContext *moc = [note object];
NSManagedObjectModel *mom = [[moc persistentStoreCoordinator] managedObjectModel];
NSEntityDescription *authorEntity = [[mom entitiesByName] objectForKey:@"Author"];
for (NSManagedObject *author in [moc updatedObjects]) {
if ([author entity] == authorEntity) {
if (![author hasFaultForRelationshipNamed:@"books"] && ([[author books] count] == 0)) {
[moc deleteObject:author];
}
}
}
}
Note: You can not pass nil
as the object (i.e. context) to observe, since frameworks you use, might have their own context, and you do not want to mess with them.
Also, note how this code is careful not to touch the author
object if it's a fault. If a book is deleted, Core Data will change the corresponding author objects' inverse relationships, hence fault in that relationship, such that it is no longer a fault. And the code will only operate on those objects.