Core Data delete rule -- to-many relationship, delete when empty

You could override prepareForDeletion in your Book class and check if the author has any other books. If not you could delete the author.

- (void)prepareForDeletion {
    Author *author = self.author;
    if (author.books.count == 1) { // only the book itself
        [self.managedObjectContext deleteObject:author];
    }
}

Edit: To prevent deletion of an author with books you could override validateForDelete or even better: don't call deleteObject with an author with books in the first place


Rickstr,

Check below for the relationships to get your two criteria done.

  1. Author -- (Deny) -->> Books

deleting an Author whose books relationship is non-empty should not be allowed

DENY: If there is at least one object at the relationship destination, then the source object cannot be deleted.

  1. Book -- (Cascade)-- > Author

deleting the last Book referencing a particular Author should delete that Author

You cannot delete the Author, as our first rule is saying, if there are any Books which are non-empty should not be deleted. If they are not present the Author gets deleted.

I think theoretically it should work. Let me know, if this works or not.


Similarly to Tim's solution, you can override the willSave method in your Author NSManagedObject subclass. Note that if you do use Tim's solution, I highly recommend filtering the books set for books that haven't been deleted; this way if you delete all of the Author's books at the same time, the Author will still be deleted.

- (void)willSave {
    if (!self.isDeleted) {
        NSPredicate *notDeletedPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary<NSString *,id> *bindings) {
            return ![(NSManagedObject *)evaluatedObject isDeleted];
        }];
        NSSet *filteredBooks = [self.books filteredSetUsingPredicate:notDeletedPredicate];
        if (filteredBooks.count == 0)
            [self.managedObjectContext deleteObject:self];
    }
    [super willSave];
}