Core Data with pre-filled .sqlite (Swift3)

Hey guys,


currently I'm working on a Swift3 / iOS10 update of an existing iOS9 App which stores about 10.000 charging points for electric vehicles across europe. Up to now I always shipped the Application with a pre-filled database (.sqlite, .sqlite-shm, .sqlite-wal files from the .xcappdata bundle), but with the current Version Apple is introducing the NSPersistentContainer Class, which makes it a bit more complicated. In my AppDelegate Class I'm instantiating my NSPersistentContainer object and passing it to a lazy var like it's done by Apple in every example code:


   lazy var stationDataPersistentContainer: NSPersistentContainer = {
        /*
         The persistent container for the application. This implementation
         creates and returns a container, having loaded the store for the
         application to it. This property is optional since there are legitimate
         error conditions that could cause the creation of the store to fail.
         */
        let container = NSPersistentContainer(name: "StationData")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                /*
                 * Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()


In the iOS9 version im copying the files to the apropriate directory, like you can see in the following code example:

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("StationData.sqlite")
    let fileMgr = NSFileManager.defaultManager()
    if !fileMgr.fileExistsAtPath(url.path!) {
          do {
               try fileMgr.copyItemAtPath(NSBundle.mainBundle().pathForResource("StationData", ofType: "sqlite")!, toPath: self.applicationDocumentsDirectory.URLByAppment("StationData.sqlite").path!)
               try fileMgr.copyItemAtPath(NSBundle.mainBundle().pathForResource("StationData", ofType: "sqlite-shm")!, toPath: self.applicationDocumentsDirectory.URLByAppendingPathComponent("StationData.sqlite-shm").path!)
               try fileMgr.copyItemAtPath(NSBundle.mainBundle().pathForResource("StationData", ofType: "sqlite-wal")!, toPath: self.applicationDocumentsDirectory.URLByAppendingPathComponent("StationData.sqlite-wal").path!)
          } catch {
               //
          }
          do {
               try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url,
                                                           options: [NSMigratePersistentStoresAutomaticallyOption:true, NSInferMappingModelAutomaticallyOption:true])
          } catch {
               //
          }
     } else {
          //
     }
     return coordinator
}()


For a number of days I have tried to move the files to the proper directory which is returned by NSPersistentContainer.defaultDirectoryURL() -> URL, but everytime I get an error, that the file already exists because my stationDataPersistentContainer is already initialized and so the NSPersistentContainer had enough time to generate the sqlite* files. Even if I try to copy the files and initialize the stationDataPersistentContainer in an overwritten init() function I could not get this right. Is there anything I'm missing or overlooking in the documentation? Which is the best/right/appropriate way to copy existing data on installation of an App into coredata.


Appendix:

Just for your Information, I could also store the JSON-Files, which i get from my API into the Documents directory and run the JSON-parser, but this needs a lot of ressources and especially time!

This is what I did, maybe it will work for you.

Technical Note TN2350

Working with Default Data in Core Data Apps


Creating a Default Data Store

A default data store should be created with Core Data APIs and exactly the same Core Data model file used in your app. You can write a tool to do that but your app can be the tool if it already has the capability to maintain its data store. You can use your app to create an empty store, then add the default data manually (if it has the UI) or write extra code for batch preloading. For an UUID attribute that is used to uniquely identify a default data record (as discussed in Working with a large default data set section), call

NSUUID().UUIDString
to retrieve an UUID and use it as the attribute value.


After populating all the data, you can grab the store file from your app's sandbox on your device or iOS Simulator, then add it into your project and use it as a default data store.


So I took the populated store and replace it for the empty one in my ..documentsDirectory

of course putting a copy in my program too for the if !FileManager.default.fileExists thing.


https://developer.apple.com/library/content/technotes/tn2350/_index.html#//apple_ref/doc/uid/DTS40017577-CH1-HEADING4

https://forums.developer.apple.com/message/162600

Core Data with pre-filled .sqlite (Swift3)
 
 
Q