2017-09-02 146 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)複製到文檔文件夾中。

相關問題