I am trying to perform a migration between two versions of CoreData that differ fundamentally to the fact that the new version has two configurations so I can save entities in two different sqlite file (one read-only in Main Bundle and one, the old sqlite, used now only for user data). I also added a model mapping to map the differences, especially to reset relationships between the entities that are lost due to multiple configurations.
The app works properly without crash if installed from scratch and new records are inserted in user data sqlite in application documents directory as expected.
The problem is when I try a migration from previous Core Data version: the app start without crash but on first executeFetchRequest
it crash at coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Userdata", URL: urlUser, options: optionsUser, error: &errorUser)
(viewed with debug) and console return this log:
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"; }
This is my code:
Old version 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
}()
New version 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
}()
Someone know how can I resolve this issue?
Thanks for the help!
EDIT
I did some test and I found that commenting coordinator!.addPersistentStoreWithType (NSSQLiteStoreType, configuration: "Questions", URL: url, options: options, error: & error)
for the first database, the application starts without issues, obviously without the content of the database not added. If I reverse the addition of the two database the app crashes with same log except for "URL: file:[...]" that it's called on the ex-first now-second database ("MedAbilityDomande.sqlite"); in practice it's the addition of the second database the problem and not a specific database. It seems that migrating the old database to the new one used for user data actually doesn't migrate configurations, so remains the old configuration that goes to overlap the entities with the new read-only database inserted into the mainBundle. As I have previously said if the app start from scratch (without migration) works perfectly.
Do you have any idea?
Thank you so much again!