我对Core Data中关系的删除规则如何工作有点模糊,至少超出了文档中描述的简单情况。
大多数情况,以及我在这里看到的问题的大多数答案都使用了一个模型,其中一对多关系左侧的对象“拥有”右侧的对象:例如Person
有PhoneNumber
个,如果删除该人,则删除所有关联的号码。在这种情况下,解决方案很明确:如果您设置如此关系,Core Data将为您处理所有事情:
Person --(cascade)-->> PhoneNumber
PhoneNumber --(nullify)--> Person
我感兴趣的是相反的情况:“所有权”相反的多对多关系。例如,我可能会扩展CoreDataBooks示例代码以添加Author
实体,以便在一个位置收集有关唯一作者的所有信息。 Book
有一位作者,但作者有很多书......但我们并不关心我们没有列出书籍的作者。因此,不应允许删除Author
关系非空的books
,删除引用特定Book
的最后Author
应该删除Author
我可以想象手动执行此操作的几种方法......我不确定的是:
答案 0 :(得分:14)
您可以覆盖prepareForDeletion
课程中的Book
,并检查作者是否还有其他书籍。如果没有,你可以删除作者。
- (void)prepareForDeletion {
Author *author = self.author;
if (author.books.count == 1) { // only the book itself
[self.managedObjectContext deleteObject:author];
}
}
编辑:为了防止删除带书籍的作者,您可以覆盖validateForDelete
甚至更好:不要首先使用带书籍的作者调用deleteObject
答案 1 :(得分:2)
Rickstr,
检查以下关系以完成两个标准。
作者 - (拒绝) - >>图书
删除不应允许其图书关系非空的作者
DENY:如果关系目标中至少有一个对象,则无法删除源对象。
书 - (级联) - >作者
删除引用特定作者的最后一本书应删除该作者
您不能删除作者,因为我们的第一条规则是,如果有任何非空的书籍不应删除。如果它们不存在则会删除作者。
我认为理论上应该有效。如果这有效,请告诉我。
答案 2 :(得分:1)
与Tim的解决方案类似,您可以覆盖作者willSave
子类中的NSManagedObject
方法。请注意,如果您使用Tim的解决方案,我强烈建议您过滤为尚未删除的图书设置的图书;这样,如果您同时删除所有作者的书籍,作者仍将被删除。
- (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];
}
答案 3 :(得分:0)
以下内容对我有用:
将您的作者实体的“书”关系上的删除规则设置为“拒绝”,这意味着只要有一本书链接到您的作者,就无法删除。
子类化您的图书实体,并按如下所示重写prepareForDeletion()函数:
public override func prepareForDeletion() {
super.prepareForDeletion()
do {
try author.validateForDelete()
managedObjectContext?.delete(author)
} catch {}
}
除非书本关系为空,否则验证删除将引发错误。 您可以选择处理错误。