iOS - 核心数据 - 在 NSManagedObject 子类中使用删除方法后保存不成功
Posted
技术标签:
【中文标题】iOS - 核心数据 - 在 NSManagedObject 子类中使用删除方法后保存不成功【英文标题】:iOS - core data - save unsuccessful after using remove methods in NSManagedObject Subclasses 【发布时间】:2012-05-15 12:59:45 【问题描述】:概述:
-
我使用提供的删除方法删除 NSManagedObject
自动生成的 NSManagedObject 子类
然后我尝试保存数据库
数据库保存失败。
.
- (void)removeEmployees:(NSSet *)values; //Auto generated method in Department.h
但是使用 add 方法添加 NSManagedObject 可以成功保存数据库
- (void)addEmployeesObject:(Employee *)value; //Auto generated method in Department.h - works fine
注意:我使用的是 XCode 生成的 NSManagedObject 子类。
实体详情:
我有 2 个表(实体),即“员工”和“部门” 一个部门可以包含多名员工 一名员工只能属于一个部门关系详情:
“员工”与“部门”的关系是一对一的关系,称为“哪个部门”。删除规则为 Nullify 从“部门”到“员工”的关系是多对一关系,称为“员工”。删除规则是级联问题:
“部门”类有一个方法调用如下,我使用这个方法后,数据库保存不成功
(void)removeEmployees:(NSSet *)values; //Auto generated method in Department.h //does not work
用于删除的代码:
- (void) removeEmployeesHavingAgeAsZeroWithDepartment: (Department*) department
NSMutableSet *employeesSetToBeRemoved = [[NSMutableSet alloc] init];
for(Employees *currentEmployee in department.employees)
if(currentEmployee.age == 0)
[employeesSetToBeRemoved addObject:currentEmployee];
[department removeEmployees:employeesSetToBeRemoved]; //causing the problem
用于保存数据库的代码
[self.database saveToURL:self.database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success)
NSLog(@"DB saved");];
问题:
-
为什么使用remove方法保存数据库不成功?
我需要实现这个方法吗?目前我没有看到这个方法的任何实现,我只能在头文件中找到它。
我的关系(反向、删除规则等)是否设置正确?
答案:
请参考 Jody 的回答和 cmets(5 月 17 日 4:39),很好地解释了如何调试问题并找到根本原因【问题讨论】:
所以它没有崩溃,它只是不删除项目?您是否尝试在调用 removeEmployees 后保存上下文?我知道如果您从 NSOrderedSet 添加/删除项目,自动生成的代码中存在错误,但这应该可以正常工作。 它不会崩溃,但不会删除记录。单独添加似乎如上所述工作 【参考方案1】:我打赌你没有保存你的上下文。当你删除一个对象时,它只是被标记为在下次保存上下文时被删除。
如果你对每个对象调用 isDeleted,你会得到什么?
编辑
啊...我看到您正在使用 UIManagedDocument(我可以通过您正在使用的保存调用来判断)。您应该在问题中提供完整的详细信息,尤其是在处理 CoreData 时,因为它有很多旋钮和交互。
好的,首先,UIManagedDocument 是一个“无保存”架构。使用 UIManangedDocument 时不应求助于 saveToURL。
它会自动将自己保存在后台线程中。但是,您必须告诉它有更新要更改。
另外,你怎么知道它没有保存?我知道这听起来像是一个奇怪的问题,但重要的是要知道你在看什么,以及你是如何确定文档没有保存的。
文档指出,如果你想保存,你需要做两件事之一。
-
使用 UndoManager 并让它标记脏东西
调用[文档updateChangeCount:UIDocumentChangeDone];
现在,实际保存将在未来某个被破坏的时间发生。但是,有些事情(比如进入后台)会触发保存。
再一次,你怎么知道数据没有保存?
您是否只是查看托管对象、从 MOC 获取、查看文件?
添加
[self.database updateChangeCount:UIDocumentChangeDone];
在删除功能结束时,您的数据肯定会被保存。
编辑
很遗憾,如果出现错误,后台保存可能会静默失败。因此,您应该注意状态更改通知,因为这是您收到的唯一通知,会发生错误。
虽然您会在状态因错误而发生更改时收到通知,但您不会收到有关错误原因的详细信息。为此,如果您需要实际的 NSError 详细信息,则必须在 UIManagedDocument 的子类中覆盖 handleError:userInteractionPermitted:。
我会注册状态更改通知并提供 UIManagedDocument 的一个简单子类,其中 handleError:userInteractionPermitted: 被覆盖以记录错误。看看那告诉你什么。希望它会引导您了解为什么没有进行保存。
另外,不要忘记您必须等待保存。
最后,如果您想查看 CoreData 在 SQL 级别执行的操作,请在命令行选项中设置调试 (-com.apple.CoreData.SQLDebug 1) 以查看 SQLLite 语句。
【讨论】:
乔迪,你是对的。我确实保存了数据库,但是数据库保存不成功。当我使用自动生成的删除方法时,保存不成功。有什么理由吗?我的关系和删除规则设置是否正确 乔迪,我已经修改了问题,你能看看吗 我最初使用了[self.database updateChangeCount:UIDocumentChangeDone];
,但没有运气,当我查询数据库(使用 SQLLite 应用程序)时,数据没有被删除。我什至尝试将应用程序退出(不退出)到主屏幕,以确保会触发保存。我认为我的删除规则/关系可能有问题。
您是否遇到任何错误?您应该注意状态更改通知,因为这是您将收到的唯一通知。您至少可以查看是否有错误。如果您想要实际的 NSError 详细信息,则必须在子类中覆盖 handleError。我会注册状态更改通知并提供 UIManagedDocument 的一个简单子类,其中的 handleError 被覆盖以记录错误。看看那告诉你什么。此外,您必须等待保存。在命令行选项中设置调试 (-com.apple.CoreData.SQLDebug 1) 以查看 SQLLite 语句。
非常感谢乔迪,听起来是正确的方法,非常感谢,不幸的是我遇到了另一个问题,我会在我尝试后告诉你。再次感谢 !!!真的很感激【参考方案2】:
经过一番调查,我意识到数据库没有得到保存。
我没有使用自动生成的删除方法,而是使用了NSManagedObjectContext
的deleteObject
方法
修复:
[self.managedObjectContext deleteObject:currentEmployee];
【讨论】:
以上是关于iOS - 核心数据 - 在 NSManagedObject 子类中使用删除方法后保存不成功的主要内容,如果未能解决你的问题,请参考以下文章