Ich versuche, den Core Data Data Stack neu zu erstellen, wenn eine Lightweight-Migration fehlgeschlagen ist, und den Benutzer zurück zum Anmeldebildschirm zu senden. Ich teste das, indem ich eine Zu-Viele-Beziehung zu einer Eins-zu-Eins-Beziehung ändere.Fehler beim Neuaufbau/Zurücksetzen von Core-Daten
Zuerst verwendete ich die gleiche URL (storeURL), wenn ich den neuen persistentStoreCoordinator nach dem Entfernen hinzufügte; Ich habe jedoch eine Fehlermeldung "Kann nicht denselben Speicher zweimal hinzufügen" in rebuildCoreData() in der Zeile "versuchen Sie persistantStoreCoordinator.add ..."
Zweitens habe ich beschlossen, die URL im neuen persistenten Speicher zu ändern durch Anhängen einer "1", so dass es selb.applicationDocumentsDirectory.URLByAppendingPathComponent ("SingleViewCoreData1.sqlite") wurde. Dies hat einen Schritt in die richtige Richtung gemacht - noch keine Fehler, und ich bin in der Lage, auf den Login-Bildschirm zurückzukehren. Nach dem Versuch, den ersten Speichervorgang nach der Anmeldung durchzuführen, erhalte ich jedoch die Fehlermeldung 'Dieser NSPersistentStoreCoordinator hat keine persistenten Speicher (Schema-Mismatch oder Migrationsfehler). Es kann keine Speicheroperation ausgeführt werden.
Was mache ich hier falsch?
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.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
let options = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
self.rebuildCoreData()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
managedObjectContext.mergePolicy = NSRollbackMergePolicy //This policy discards in-memory state changes for objects in conflict. The persistent store’s version of the objects’ state is used
return managedObjectContext
}()
// MARK: - Tearing down core data stack and rebuilding it in the case that a lightweight migration fails
func rebuildCoreData() {
let storeURL = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
do {
try NSFileManager.defaultManager().removeItemAtURL(storeURL)
} catch {
print(error)
abort()
}
for object in managedObjectContext.registeredObjects {
managedObjectContext.deleteObject(object)
}
do {
try persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true])
} catch {
print(error)
abort()
}
print("successfully rebuilt core data")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateInitialViewController()
self.window?.rootViewController?.presentViewController(controller!, animated: false, completion: nil)
}
UPDATE - Geänderte Löschen von Dateien und bearbeitet persistenten Speicher Koordinator Logik im catch-Block
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
var coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
let options = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
//rebuilds core data
coordinator = self.rebuildCoreData(coordinator)
}
return coordinator
}()
New rebuildCoreData Code:
// MARK: - Tearing down core data stack and rebuilding it in the case that a lightweight migration fails
func rebuildCoreData(coordinator: NSPersistentStoreCoordinator) -> NSPersistentStoreCoordinator {
let persistentStoreParentPath = self.applicationDocumentsDirectory.path
let fileEnumerator = NSFileManager.defaultManager().enumeratorAtPath(persistentStoreParentPath!)
while let path = fileEnumerator?.nextObject() as? String {
if path.hasPrefix("SingleViewCoreData.sqlite") || path.hasPrefix(".SingleViewCoreData.sqlite") {
let pathToDelete = (persistentStoreParentPath! as NSString).stringByAppendingPathComponent(path)
do {
try NSFileManager.defaultManager().removeItemAtPath(pathToDelete)
}
catch _ {
// Handle error removing file
}
}
}
for object in managedObjectContext.registeredObjects {
managedObjectContext.deleteObject(object)
}
do {
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true])
} catch {
print(error)
abort()
}
print("successfully rebuilt core data")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateInitialViewController()
self.window?.rootViewController?.presentViewController(controller!, animated: false, completion: nil)
return coordinator
}
Können Sie bitte ein Beispielcode-Snippet bereitstellen? Und was ist mit dem zweiten Fehler, den ich bekam, wo NSPersistentStoreCoordinator keine persistenten Speicher hat? –
@mckamike Möchten Sie ein Beispiel zum Aufzählen und Löschen von Dateien? Nachdem Ihre 'CoreData'-Dateien gelöscht wurden, würde ich einfach den gesamten' CoreData'-Stack neu erstellen. Sie sparen nicht viel, indem Sie den zuvor erstellten Koordinator beibehalten. –
Ja zu Ihrer Frage, und zu Ihrer zweiten Aussage, wie kann ich sie "neu erstellen"? –