Objective c 核心数据删除规则——对多个关系,空时删除
我对核心数据中关系的删除规则是如何工作的有点模糊,至少在文档中描述的简单案例之外 大多数情况下,以及我在这里看到的大多数问题的答案,都使用一个模型,其中一对多关系左侧的对象“拥有”右侧的对象:例如Objective c 核心数据删除规则——对多个关系,空时删除,objective-c,core-data,Objective C,Core Data,我对核心数据中关系的删除规则是如何工作的有点模糊,至少在文档中描述的简单案例之外 大多数情况下,以及我在这里看到的大多数问题的答案,都使用一个模型,其中一对多关系左侧的对象“拥有”右侧的对象:例如PersonhasPhoneNumbers,如果删除此人,则删除其所有相关号码。在这种情况下,解决方案是明确的:如果您这样设置关系,核心数据将为您处理一切: Person --(cascade)-->> PhoneNumber PhoneNumber --(nullify)--&g
Person
hasPhoneNumber
s,如果删除此人,则删除其所有相关号码。在这种情况下,解决方案是明确的:如果您这样设置关系,核心数据将为您处理一切:
Person --(cascade)-->> PhoneNumber
PhoneNumber --(nullify)--> Person
我感兴趣的是相反的:一种“所有权”颠倒的对多关系。例如,我可以扩展CoreDataBooks示例代码,添加一个作者
实体,用于在一个地方收集关于唯一作者的所有信息。一本书有一个作者,但是一个作者有很多书。。。但是我们不关心那些我们没有列出书籍的作者。因此,不允许删除其书籍
关系为非空的作者
,删除引用特定作者的最后一本书籍
应删除该作者
我可以想象几种手动操作的方法。。。我不确定的是:
- 核心数据是否有一种方法可以至少自动完成其中的一部分,就像关系删除规则一样
- 有没有一种“规范的”首选方法来处理这种情况
您可以覆盖书籍
类中的preparefordelection
,并检查作者是否还有其他书籍。如果没有,你可以删除作者
- (void)prepareForDeletion {
Author *author = self.author;
if (author.books.count == 1) { // only the book itself
[self.managedObjectContext deleteObject:author];
}
}
编辑:为了防止删除拥有书籍的作者,您可以覆盖validateForDelete
或者更好:首先不要对拥有书籍的作者调用deleteObject
检查下面的关系,以完成两个标准
作者--(拒绝)-->>书籍
不允许删除书籍关系为非空的作者
拒绝:如果关系目标至少有一个对象,则无法删除源对象
- (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];
}
书--(级联)-->作者
删除引用特定作者的最后一本书应删除该作者
您不能删除作者,正如我们的第一条规则所说,如果有任何非空的书籍,则不应删除。如果它们不存在,作者将被删除
我认为理论上它应该是有效的。让我知道,这是否有效 与Tim的解决方案类似,您可以覆盖AuthorNSManagedObject
子类中的willSave
方法。请注意,如果您确实使用了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];
}
-(void)将保存{
如果(!self.isDeleted){
NSPredicate*notDeletedPredicate=[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject,NSDictionary*绑定){
return![(NSManagedObject*)evaluatedObject已删除];
}];
NSSet*filteredBooks=[self.books filteredSetUsingPredicate:notDeletedPredicate];
if(filteredBooks.count==0)
[self.managedObjectContext删除对象:self];
}
[超级保存];
}
以下几点对我很有用:
将您的作者实体的“书籍”关系的删除规则设置为“拒绝”,这意味着只要有一本书链接到您的作者,它就不能被删除
- (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];
}
对book实体进行子类化并重写PrepareForderElection()函数,如下所示:
public override func prepareForDeletion() {
super.prepareForDeletion()
do {
try author.validateForDelete()
managedObjectContext?.delete(author)
} catch {}
}
除非账簿关系为空,否则Validate for delete将引发错误。
您可以选择处理错误。Author-(Deny)->>Books
很好,但是Book-(Cascade)->Author
会在删除作者的第一本书时立即删除作者。(要么是这样,要么是我做错了什么。)但是同一个作者被绑定了否认关系的权利,所以理论上它不会被删除,因为他有另一本书。除非有其他事情发生,否则如果一个作者的两本书同时被删除,这似乎是失败的。我正在打印author.books.count在我相应的preparefordelection中的值,这两本书的值都是2。那么作者永远不会被删除。(更改类名以匹配问题,但关系相同。)