将persistentStoreCoordinator sqlite文件迁移到新名称

时间:2017-04-13 18:07:49

标签: ios swift core-data

当我尝试解决sqlite文件的问题时,我意识到我的AppDelegate出错了。

let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")

我想更改文件名以匹配应用名称,但我不想丢失SingleViewCoreData.sqlite文件中的当前数据。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:0)

这是我能够解决问题的方法,这一切都是 Swift 3.1

var pURL: URL?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    checkForOldStore()
    return true
}

然后我编辑了persistentStoreCoordinator部分。

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added 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.
        // Create the coordinator and store
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
//        let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
        let url = self.pURL // ADDED THIS CODE WHICH REPLACED CODE FROM ABOVE.
        var failureReason = "There was an error creating or loading the application's saved data."
        do {
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: [NSMigratePersistentStoresAutomaticallyOption: true,
                NSInferMappingModelAutomaticallyOption: true])
        } catch {

使用以下代码,我首先检查旧的sqlite文件是否与checkForOldStore()一起存在。请注意,在调用persistentStoreCoordinator之前,如果文件存在,我将pURL设置为等于migrateStore()上旧设置的值。并且因为每次应用程序启动时checkForOldStore()仍然运行,现在该文件不存在,我将pURL设置为新文件名。

    func checkForOldStore() {
    let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
    let url = NSURL(fileURLWithPath: path)
    let filePath = url.appendingPathComponent("SingleViewCoreData.sqlite")?.path
    let fileManager = FileManager.default
    if fileManager.fileExists(atPath: filePath!) {
        print("FILE AVAILABLE")
        pURL = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
        migrateStore()
    } else {
        pURL = self.applicationDocumentsDirectory.appendingPathComponent("NewName.sqlite")
        print("FILE NOT AVAILABLE")
    }
}

migrateStore()的末尾,我为每个旧的sqlite文件调用remvoeOldDB

func migrateStore() {
    // migrate current store from one URL to another
    // write out the current store URL before the migration
    var storeURL: URL? = persistentStoreCoordinator.persistentStores.last?.url
    print("Current Store URL (before migration): \(String(describing: storeURL?.description))")
    // grab the current store
    let currentStore: NSPersistentStore? = persistentStoreCoordinator.persistentStores.last
    // create a new URL
    let newStoreURL: URL? = applicationDocumentsDirectory.appendingPathComponent("NewName.sqlite")
    // setup new options dictionary if necessary
    // migrate current store to new URL
    _ = try? persistentStoreCoordinator.migratePersistentStore(currentStore!, to: newStoreURL!, options: nil, withType: NSSQLiteStoreType)
    // and to check we're on the new store, write out tha URL again
    storeURL = persistentStoreCoordinator.persistentStores.last?.url
    print("Current Store URL (after migration): \(String(describing: storeURL?.description))")
    removeOldDB(itemName: "SingleViewCoreData", fileExtension: "sqlite")
    removeOldDB(itemName: "SingleViewCoreData", fileExtension: "sqlite-shm")
    removeOldDB(itemName: "SingleViewCoreData", fileExtension: "sqlite-wal")

}

func removeOldDB(itemName:String, fileExtension: String) {
    let fileManager = FileManager.default
    let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
    let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
    let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
    guard let dirPath = paths.first else {
        return
    }
    let filePath = "\(dirPath)/\(itemName).\(fileExtension)"
    do {
        try fileManager.removeItem(atPath: filePath)
    } catch let error as NSError {
        print(error.debugDescription)
    }
}