目标: 我想检查托管对象以确保可以删除
期望: -[NSManagedObject validateForDelete:]
应该根据管理对象模型中的删除规则设置返回一个 BOOL
NSManagedObject 类引用
阅读本文我假设我应该能够做这样的事情:
BOOL canDelete = [myManagedObject validateForDelete:&error];
if (canDelete) {
[managedObjectContext deleteObject:myManagedObject];
}
else {
[self requestUserFeedback];
}
但是,此方法几乎总是返回
NO
。示例代码
托管对象模型
Department
- Attribute: name
- Value: String
- Relationship: employees
- To Many
- Destination: Employee
- Delete Rule: Nullify
- Inverse: department
Employee
- Attribute: name
- Value: String
- Relationship: department
- To One
- Destination: Department
- Delete Rule: Nullify
- Inverse: employees
示例代码:
NSManagedObject *department = [NSEntityDescription insertNewObjectForEntityForName:@"Department" inManagedObjectContext:self.managedObjectContext];
for (int i = 0; i < 10; i++) {
NSManagedObject *employee = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:self.managedObjectContext];
[employee setValue:department forKey:@"department"];
if ([employee validateForDelete:NULL]) {
NSLog(@"Can delete employee");
}
else {
NSLog(@"WARNING: Cannot delete employee");
}
}
NSError *error;
BOOL canDelete = [department validateForDelete:&error];
if (canDelete) {
NSLog(@"Can delete department");
}
else {
NSLog(@"WARNING: Cannot delete department");
}
输出:
令我惊讶的是,
canDelete
是 NO
。当员工对象不无效时,为什么部门对象会被删除无效?返回的错误包含以下内容(缩写)Error Domain=NSCocoaErrorDomain
Code=1600
UserInfo= <>{
NSValidationErrorObject=< department object >
NSValidationErrorKey=employees
NSValidationErrorValue=Relationship 'employees' on managed object
}
因此,
validateForDelete:
没有返回我对多对关系的期望值,但确实返回对一关系的期望值。但是,请返回文档一秒钟:这说明了 validateForDelete: 的默认实现是如何工作的,并共同努力引起人们对“拒绝”删除规则的注意。没有提及取消或级联删除规则或一对一或多对关系之间的差异。
进一步的研究
谷歌搜索出现 this hit on the Apple Mailing List archives from 2009 ,它基本上说:
-[NSManagedObject validateForDelete:]
是一个子类的钩子(Hook),你需要在一个单独的方法中实现你自己的逻辑来确定一个对象是否有效删除。什么?这是真的?这不是这种方法的文档会让人相信的:
我们如何检查托管对象是否处于可以删除的状态?
我在 GitHub 上设置了一个小示例项目,它通过生产代码和单元测试说明了我的发现。
最佳答案
我阅读文档的方式是您应该将其子类化,但您的子类也应该首先调用 super
,以便如果框架本身中有验证,您也将捕获它。
根据我的经验,-validateForDelete:
只在拒绝规则上返回 NO
。
我的建议是将关系规则设置为“无操作”,然后在您的子类中实现逻辑。
在您的子类中,您可以检查与部门/教室的关系,如果计数为零,则返回 YES
。模型中无法实现的非常简单的删除验证规则。