无法销毁使用Core Data和SQLite创建的持久性存储

时间:2018-08-23 22:50:22

标签: ios swift core-data

我有一个iOS应用,我希望在每次启动时都从一个新的Core Data数据库开始。商店类型为SQLite。

但是,当我调用persistentStoreCoordinator.destroyPersistentStore()时,我会在100%的时间内出现错误。

代码如下:

func destroyPersistentStore() {
    guard let modelURL = Bundle.main.url(forResource: self.modelName, withExtension: "momd") else {
        print("Missing data model - could not destroy")
        return
    }

    do {
        try persistentStoreCoordinator.destroyPersistentStore(at: modelURL, ofType: storeType, options: nil)
    } catch  {
        print("Unable to destroy persistent store: \(error) - \(error.localizedDescription)")
   }
}

错误是:

  

无法销毁永久存储:Error Domain = NSSQLiteErrorDomain   代码= 14“(空)” UserInfo = {NSFilePath = ... / AppName.app/ModelName.momd,   原因=无法截断数据库}-无法执行该操作   完成。 (NSSQLiteErrorDomain错误14。)

即使发生此错误,该应用程序也可以保存和访问商店中的数据。问题在于每次启动时都会加载初始数据,从而创建重复项。

在这种情况下,发生了对destroyPersistentStore的调用:

  1. SQLite数据文件确实存在并包含数据
  2. 发生在模拟器或真实设备上
  3. modelUrl是正确的,并指向提示
  4. 商店类型为SQLite
  5. SQLite数据文件保存在Documents目录中
  6. persistentStoreCoordinator.url(用于:persistentStoreCoordinator.persistentStores.first!)指向“文档”目录中的文件。

我已经在线搜索了答案,但是找不到任何人报告此错误,但是我在此项目和简化的演示项目中均遇到了错误。我根本无法使destroyPersistentStore正常工作。

最后,当我暂停执行并放置persistentStoreCoordinator.managedObjectModel时,第一行是:

  

popersistentStoreCoordinator.managedObjectModel   ()isEditable 0,实体...

是isEditable问题吗?我该如何更改?

2 个答案:

答案 0 :(得分:1)

您要在Core Data堆栈中合并两个对象:

  • 模型位于您的应用包中,扩展名为.momd,其中包含有关Core Data对象定义的信息:您拥有哪些实体,它们具有哪些属性,它们之间的关系,等等。
  • 持久性存储是应用容器中(而不是捆绑包中)的数据文件。您在创建或加载持久性存储时定义其URL。它包含模型对象实际实例的数据,而不是抽象定义。

我认为您不是要获取模型的URL,而是要获取持久性存储的URL。您可以通过查看持久性存储协调器的persistentStores数组,选择一个数组并获取其URL来做到这一点:

func destroyPersistentStore() {
    guard let firstStoreURL = persistentStoreCoordinator.persistentStores.first?.url else {
        print("Missing first store URL - could not destroy")
        return
    }

    do {
        try persistentStoreCoordinator.destroyPersistentStore(at: firstStoreURL, ofType: storeType, options: nil)
    } catch  {
        print("Unable to destroy persistent store: \(error) - \(error.localizedDescription)")
   }
}

这将摧毁第一家商店;如果您有多个存储,则可以根据应用程序的需求,循环遍历持久性存储,将其全部销毁。

答案 1 :(得分:0)

找到了一个很好的解决方案:

import Foundation
import CoreData

extension NSManagedObjectContext
{
    func deleteAllData()
    {
        guard let persistentStore = persistentStoreCoordinator?.persistentStores.last else {
            return
        }

        guard let url = persistentStoreCoordinator?.url(for: persistentStore) else {
            return
        }

        performAndWait { () -> Void in
            self.reset()
            do
            {
                try self.persistentStoreCoordinator?.remove(persistentStore)
                try FileManager.default.removeItem(at: url)
                try self.persistentStoreCoordinator?.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
            }
            catch { /*dealing with errors up to the usage*/ }
        }
    }
}