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】:

经过一番调查,我意识到数据库没有得到保存。

我没有使用自动生成的删除方法,而是使用了NSManagedObjectContextdeleteObject方法

修复:

[self.managedObjectContext deleteObject:currentEmployee];

【讨论】:

以上是关于iOS - 核心数据 - 在 NSManagedObject 子类中使用删除方法后保存不成功的主要内容,如果未能解决你的问题,请参考以下文章

在核心绘图 iOS 中动态获取绘图范围的数据

IOS/xcode:将核心数据从应用委托移动到模型类

核心数据在 iOS 4.3 中不起作用

如何解决:为啥核心数据(NSFetchedResultsController)在 iOS5 和 iOS 4 中排序不同

iOS - 核心数据 - 完成处理程序

如何在 ios 中的单元格上显示核心数据?