从可能损坏的Core Data数据库中恢复

时间:2018-01-15 22:43:38

标签: ios core-data

我有一个iOS应用程序,可将其数据存储在Core Data数据库中。基本结构具有Libraries和Items,它们之间具有多对多关系,由LibraryItemMapping表示。映射项包含索引,因此可以在不同的容器中对项进行不同的排序。这在大多数情况下都可以正常工作,但是在我用于dev / test的我自己的设备上,我遇到了Core Data对象为一侧或另一侧关系返回nil的情况。如果我在启动时枚举这些对象(通过AppDelegate中的代码),那么nils就会消失,我能够在关系的任何一侧检索对象,但是在几秒钟后他们开始返回相同的关系时零。例如,这总是运行正常,永远不会出错或找到任何nils:

public func runConsistencyCheck() {
    do {
        let mappings = try dataContext.fetch(NSFetchRequest<LibraryItemMapping>(entityName: "LibraryItemMapping"))
        for map in mappings {
            if (map.item==nil || map.library==nil) {
                print("Found corrupt mapping record. Deleting.")
                dataContext.delete(map)
            }
        }
        saveContext()
    } catch {
        print("An error occurred during consistency checking: \(error)")
    }
}

但是这经常在我的设备上找到obj.item和/或崩溃的nil:

func getMapping(forItem item: Item) -> LibraryItemMapping? {
    if (libraryData?.itemMappings != nil) {
        for obj in libraryData!.itemMappings as! Set<LibraryItemMapping> {
            if (obj.item != nil && obj.item! == item) { return obj }
            else {
                print("Found Core Data mapping with null item data.")
            }
        }
    }
    return nil
}

尝试创建或修改然后保存任何其他记录会导致此错误的多次迭代:

"Error Domain=NSCocoaErrorDomain Code=1570 \"item is a required value.\" UserInfo={NSValidationErrorKey=item, NSLocalizedDescription=item is a required value., NSValidationErrorObject=<LibraryItemMapping: 0x174098060> (entity: LibraryItemMapping; id: 0xd0000000001c0000 <x-coredata://ED9F1AE5-A7D0-46FD-AC94-941E9EFEF341/LibraryItemMapping/p7> ; data: {\n    index = 4;\n    item = nil;\n    library = \"0xd000000000140004 <x-coredata://ED9F1AE5-A7D0-46FD-AC94-941E9EFEF341/LibraryData/p5>\";\n})}"

这只发生在我所知道的一台设备上,所以我很想把它放到一个被错误的调试会话破坏的数据库中,但至少我是这样的。喜欢能够优雅地清理它。如果这是SQL,我只会运行一致性检查和类似delete from LibraryItemMapping where item is null or library is null之类的东西并继续前进,但我不确定如何使用Core Data进行等效操作。我怎样才能进一步解决这个问题,如何从一个看似腐败的数据库中优雅地恢复?

1 个答案:

答案 0 :(得分:1)

从设备中提取sqlite文件并挖掘原始数据后,这实际上是一个数据模型错误。在应用程序启动期间,它会通过&#34;修剪旧记录&#34;步骤,并且关于链接表的关系的不一致删除规则允许它使记录处于不一致状态。在根据需要更正删除规则以使用CascadeNullify之后,所有内容都会再次运行。