2017-09-02 150 views
1

我有一个核心数据数据库,我希望预先填充而无需在首次启动时加载所有数据。我试图通过创建第二个应用程序来负责加载并将SQL数据库从该应用程序复制到新应用程序。起初我想简单地.sqlite文件从第二个应用程序拷贝和复制文件到这样的第一个应用程序:将核心数据数据库从一个应用程序迁移到另一个应用程序

lazy var persistentContainer: NSPersistentContainer = { 
     let container = NSPersistentContainer(name: "GeoPointDB") 

     let seededData: String = "GeoPointDB" 
     var persistentStoreDescriptions: NSPersistentStoreDescription 

     let storeUrl = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first! 

     if !FileManager.default.fileExists(atPath: (storeUrl.path)) { 
      let seededDataUrl = Bundle.main.url(forResource: seededData, withExtension: "sqlite") 
      try! FileManager.default.copyItem(at: seededDataUrl!, to: storeUrl) 

     } 

     container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeUrl)] 
     container.loadPersistentStores(completionHandler: { (storeDescription, error) in 
      if let error = error { 

       fatalError("Unresolved error \(error),") 
      } 
     }) 

     return container 

    }() 

然而,这给了我一个错误信息:“无法打开数据库文件”。研究了一下,我发现这篇文章: https://developer.apple.com/library/content/qa/qa1809/_index.html

因此,我又回到了第二个应用程序,并试图通过使用此代码正确导出数据库:

let documents = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first! 
       do { 
        try context.persistentStoreCoordinator!.migratePersistentStore(context.persistentStoreCoordinator!.persistentStores.first!, to: documents, options: nil, withType: NSSQLiteStoreType) 
        print("Managed to save database file") 
       } catch let error as NSError { 
        print("Failed to save DB: \(error)") 
       } 

但我做到这一点时,我得到确切同样的错误出口当试图加载复制的数据库到第一个应用程序:“无法打开数据库文件”。关于我在做什么错误的任何提示或如何使用iOS 10/11和Swift 3/4执行数据库迁移?

,可能是有用的一些额外的信息:

  • 这两个应用程序都从项目创建Xcode的“使用核心数据”选项标准CoreData代码
  • 在第一个应用程序的CoreData模型(.xcdatamodeld文件)从第二应用程序复制到确保不存在任何矛盾
  • 我能够从第二应用程序的数据库没有任何问题的增加和获取数据

回答

1

最后,我设法找到了一个可行的解决方案。我还没有想出如何成功导出数据库,但由于我将只对每个应用程序更新执行一次此迁移(或不太频繁),所以我可以手动复制数据并验证数据库是否已通过简单测试而不会损坏提交给App Store。

关于数据库的导入对应的代码,这是我最后使用:

lazy var persistentContainer: NSPersistentContainer = { 
     let databaseName = "GeoPointDB" 

     let container = NSPersistentContainer(name: databaseName) 

     var persistentStoreDescriptions: NSPersistentStoreDescription 

     let storeUrl = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first!.appendingPathComponent(databaseName + ".sqlite") 
     let storeUrlFolder = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first! 

     if !FileManager.default.fileExists(atPath: (storeUrl.path)) { 
      let seededDataUrl = Bundle.main.url(forResource: databaseName, withExtension: "sqlite") 
      let seededDataUrl2 = Bundle.main.url(forResource: databaseName, withExtension: "sqlite-shm") 
      let seededDataUrl3 = Bundle.main.url(forResource: databaseName, withExtension: "sqlite-wal") 

      try! FileManager.default.copyItem(at: seededDataUrl!, to: storeUrl) 
      try! FileManager.default.copyItem(at: seededDataUrl2!, to: storeUrlFolder.appendingPathComponent(databaseName + ".sqlite-shm")) 
      try! FileManager.default.copyItem(at: seededDataUrl3!, to: storeUrlFolder.appendingPathComponent(databaseName + ".sqlite-wal")) 

     } 

     container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeUrl)] 
     container.loadPersistentStores(completionHandler: { (storeDescription, error) in 
      if let error = error { 

       fatalError("Unresolved error \(error),") 
      } 
     }) 

     return container 
    }() 

的两件事情我根本改变是为了确保该NSPersistantStoreDescription在SQL文件直接指向(而不是上面的目录),并且我将所有三个文件(.sqlite.sqlite-shm.sqlite-wal)复制到文档文件夹中。

相关问题