预填充.sqlite的核心数据(Swift3) [英] Core Data with pre-filled .sqlite (Swift3)

查看:252
本文介绍了预填充.sqlite的核心数据(Swift3)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我正在开发一个现有的iOS9应用程序Swift3 / iOS10更新,为欧洲各地的电动汽车存储大约10,000个充电点。到目前为止,我总是使用预填充的数据库(.xcappdata包中的.sqlite,.sqlite-shm,.sqlite-wal文件)运行应用程序,但是使用当前的版本苹果公司引入了 NSPersistentContainer 类,这使它有点复杂。在我的AppDelegate类中,我实例化了我的NSPersistentContainer对象,并将其传递给一个惰性的var,就像它在每个示例代码中所做的那样:

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 = {  
     let fileMgr = FileManager.default
     let destinationModel = NSPersistentContainer.defaultDirectoryURL()
     if !fileMgr.fileExists(atPath: destinationModel.appendingPathComponent("StationData.sqlite").path) {
         do {
             try fileMgr.copyItem(at: URL(fileURLWithPath: Bundle.main.resourcePath!.appending("/StationData.sqlite")), to: destinationModel.appendingPathComponent("/StationData.sqlite"))
             try fileMgr.copyItem(at: URL(fileURLWithPath: Bundle.main.resourcePath!.appending("/StationData.sqlite-shm")), to: destinationModel.appendingPathComponent("/StationData.sqlite-shm"))
             try fileMgr.copyItem(at: URL(fileURLWithPath: Bundle.main.resourcePath!.appending("/StationData.sqlite-wal")), to: destinationModel.appendingPathComponent("/StationData.sqlite-wal"))
         } catch {
             //
         }
     } else {
         //
     }
     /* 
     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  
    }()

在iOS9版本im文件到apropriate目录,就像你可以看到下面的代码示例:

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
}() 

的天我试图将文件移动到由 NSPersistentContainer.defaultDirectoryURL() - >返回的正确的目录。 URL ,但每次我得到一个错误,该文件已经存在,因为我的stationDataPersistentContainer已经初始化,所以NSPersistentContainer有足够的时间来生成sqlite *文件。即使我尝试复制文件和初始化stationDataPersistentContainer在一个覆盖的init()函数,我不能得到这个权利。在文档中有什么我缺失或忽略吗?

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.

附录:

对于你的信息,我还可以存储JSON文件,我从我的API到Documents目录并运行JSON解析器,但这需要大量的资源,特别是时间!

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 question is also posted on the Apple Developers Forum and waiting for approval)

推荐答案

这是我如何做:

lazy var persistentContainer: NSPersistentContainer = {

         let container = NSPersistentContainer(name: "app_name")

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

        let storeUrl = self.applicationDocumentsDirectory.appendingPathComponent("app_name.sqlite")

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

        }

        print(storeUrl)


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

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

         return container


    }()

这篇关于预填充.sqlite的核心数据(Swift3)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆