2015-02-23 36 views
0

我正試圖在CoreData的兩個版本之間進行遷移,這些遷移基本上與新版本具有兩種配置的事實有所不同,因此我可以將實體保存在兩個不同的sqlite文件(一個只讀在主包中,一個是舊的sqlite,現在只用於用戶數據)。我還添加了一個模型映射來映射差異,特別是重置由於多個配置而丟失的實體之間的關係。 如果從頭開始安裝,並且應用程序文檔目錄中的用戶數據sqlite中插入新記錄,應用程序將正常運行而不會崩潰。 問題是,當我試圖從以前的核心數據版本遷移:在應用程序啓動時不崩潰,但在第一次executeFetchRequest它在coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Userdata", URL: urlUser, options: optionsUser, error: &errorUser)(含調試觀看)和控制檯回報崩潰此日誌:關於核心數據版本遷移的「無法兩次添加相同的存儲」

2015-02-23 18:48:24.052 MedAbility[21480:585606] CoreData: error: -addPersistentStoreWithType:SQLite configuration:(null) URL:file:///Volumes/Documenti/Users/andrea/Library/Developer/CoreSimulator/Devices/301801BE-4B6A-4371-BE66-3E71557B0897/data/Containers/Data/Application/FBEC0124-1D74-4F94-99F2-6F492281AA8E/Documents/MedAbility.sqlite options:{ NSInferMappingModelAutomaticallyOption = 1; NSMigratePersistentStoresAutomaticallyOption = 1; } ... returned error Error Domain=NSCocoaErrorDomain Code=134080 "The operation couldn’t be completed. (Cocoa error 134080.)" UserInfo=0x7fb50ae481d0 {NSUnderlyingException=Can't add the same store twice} with userInfo dictionary { NSUnderlyingException = "Can't add the same store twice"; } 2015-02-23 18:48:24.061 MedAbility[21480:585606] CoreData: error: -addPersistentStoreWithType:SQLite configuration:Userdata URL:file:///Volumes/Documenti/Users/andrea/Library/Developer/CoreSimulator/Devices/301801BE-4B6A-4371-BE66-3E71557B0897/data/Containers/Data/Application/FBEC0124-1D74-4F94-99F2-6F492281AA8E/Documents/MedAbility.sqlite options:{ NSInferMappingModelAutomaticallyOption = 1; NSMigratePersistentStoresAutomaticallyOption = 1; } ... returned error Error Domain=NSCocoaErrorDomain Code=134080 "The operation couldn’t be completed. (Cocoa error 134080.)" UserInfo=0x7fb50ae481d0 {NSUnderlyingException=Can't add the same store twice} with userInfo dictionary { NSUnderlyingException = "Can't add the same store twice"; }

這是我的代碼:

舊版本PersistentStoreCoordinator:

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { 
     // Create the coordinator and store 
     var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 
     let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("MedAbility.sqlite") 
     var error: NSError? = nil 
     var failureReason = "There was an error creating or loading the application's saved data." 
     // Set options for migrations 
     let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true] 
     if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options, error: &error) == nil { 
      coordinator = nil 
      // Report any error we got. 
      let dict = NSMutableDictionary() 
      dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
      dict[NSLocalizedFailureReasonErrorKey] = failureReason 
      dict[NSUnderlyingErrorKey] = error 
      error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 

      NSLog("Unresolved error \(error), \(error!.userInfo)") 
     } 

     // Exclude db from backup 
     Util.addSkipBackupAttributeToItemAtURL(url) 

     return coordinator 
     }() 

新版本PersistentStoreCoordinator:

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { 
     // The persistent store coordinator for the application. This implementation creates and return 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 
     var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 

     let url = NSBundle.mainBundle().URLForResource("MedAbilityDomande", withExtension: "sqlite") 
     var error: NSError? = nil 
     var failureReason = "There was an error creating or loading the application's saved data." 
     // Set questions sqlite as read-only 
     let options = [NSReadOnlyPersistentStoreOption: true] 
     if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Domande", URL: url, options: options, error: &error) == nil { 
      coordinator = nil 
      // Report any error we got. 
      let dict = NSMutableDictionary() 
      dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
      dict[NSLocalizedFailureReasonErrorKey] = failureReason 
      dict[NSUnderlyingErrorKey] = error 
      error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 

      NSLog("Unresolved error \(error), \(error!.userInfo)") 
     } 

     let urlUser = self.applicationDocumentsDirectory.URLByAppendingPathComponent("MedAbility.sqlite") 
     var errorUser: NSError? = nil 
     var failureReasonUser = "There was an error creating or loading the application's saved data." 
     // Set migration options 
     let optionsUser = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true] 
     if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Userdata", URL: urlUser, options: optionsUser, error: &errorUser) == nil { 
      coordinator = nil 
      // Report any error we got. 
      let dict = NSMutableDictionary() 
      dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
      dict[NSLocalizedFailureReasonErrorKey] = failureReasonUser 
      dict[NSUnderlyingErrorKey] = errorUser 
      errorUser = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 

      NSLog("Unresolved error \(errorUser), \(errorUser!.userInfo)") 
     } 

     return coordinator 
     }() 

有人知道我該如何解決這個問題?

感謝您的幫助!

編輯

我做了一些測試,我發現第一個數據庫的評論coordinator!.addPersistentStoreWithType (NSSQLiteStoreType, configuration: "Questions", URL: url, options: options, error: & error),應用程序啓動時沒有問題,顯然沒有沒有加入數據庫的內容。如果我反向添加兩個數據庫,那麼應用程序會崩潰,除了在「ex-first now-second」數據庫(「MedAbilityDomande.sqlite」)上調用的「URL:file:[...]在實踐中,它是增加了第二個數據庫的問題,而不是一個特定的數據庫。看起來,將舊數據庫遷移到用於用戶數據的新數據庫實際上不會遷移配置,因此仍然是舊配置,它將實體與插入到mainBundle中的新只讀數據庫重疊。正如我之前所說的,如果應用程序從頭開始(沒有遷移),完美地工作。

你有什麼想法嗎?

非常感謝你!

回答

0

我終於找到了解決方案!我基於數據庫創建了數據庫MedAbilityDomande.sqlite,該數據庫在我想遷移以用於用戶數據之後。這帶來了兩個數據庫具有相同的UUID,從而產生錯誤"Can't add the same store twice"。只需更改應用程序包(MedAbilityDomande.sqlite)中數據庫的UUID即可,而且一切運行良好。

直到下一次!

+0

嗨我也面臨這個問題,你是如何改變捆綁中使用的數據庫的UUID? – anoop4real 2016-03-08 08:59:39

+0

嗨!我用一個軟件來打開數據庫(我使用「DB Browser for SQLite」)。然後我手動更改了表「Z_METADATA」的列「Z_UUID」上的UUID字符串。爲了確保使用有效且唯一的UUID,我創建了一個帶有臨時應用程序的新CoreData數據庫,然後始終使用「DB Browser for SQLite」,將UUID從新數據庫複製並粘貼到我想要的數據庫包括在包中。 – 2016-03-10 10:01:15

+0

非常感謝,我需要嘗試一下 – anoop4real 2016-03-10 10:35:36