@@ -38,29 +38,24 @@ extension NSPersistentContainer {
3838 throw CopyPersistentStoreErrors . invalidSource ( " Source URL must exist " )
3939 }
4040
41- for persistentStore in persistentStoreCoordinator . persistentStores {
42- guard let loadedStoreURL = persistentStore . url else {
41+ for persistentStoreDescription in persistentStoreDescriptions {
42+ guard let loadedStoreURL = persistentStoreDescription . url else {
4343 continue
4444 }
4545 let backupStoreURL = backupURL. appendingPathComponent ( loadedStoreURL. lastPathComponent)
4646 guard FileManager . default. fileExists ( atPath: backupStoreURL. path) else {
4747 throw CopyPersistentStoreErrors . invalidSource ( " Missing backup store for \( backupStoreURL) " )
4848 }
4949 do {
50- // Remove the existing persistent store first
51- try persistentStoreCoordinator. remove ( persistentStore)
52- } catch {
53- print ( " Error removing store: \( error) " )
54- throw CopyPersistentStoreErrors . copyStoreError ( " Could not remove persistent store before restore " )
55- }
56- do {
57- // Clear out the existing persistent store so that we'll have a clean slate for restoring.
58- try persistentStoreCoordinator. destroyPersistentStore ( at: loadedStoreURL, ofType: persistentStore. type, options: persistentStore. options)
59- // Add the backup store at its current location
60- let backupStore = try persistentStoreCoordinator. addPersistentStore ( ofType: persistentStore. type, configurationName: persistentStore. configurationName, at: backupStoreURL, options: persistentStore. options)
61- // Migrate the backup store to the non-backup location. This leaves the backup copy in place in case it's needed in the future, but backupStore won't be useful anymore.
62- let restoredTemporaryStore = try persistentStoreCoordinator. migratePersistentStore ( backupStore, to: loadedStoreURL, options: persistentStore. options, withType: persistentStore. type)
63- print ( " Restored temp store: \( restoredTemporaryStore) " )
50+ let storeOptions = persistentStoreDescription. options
51+ let configurationName = persistentStoreDescription. configuration
52+ let storeType = persistentStoreDescription. type
53+
54+ // Replace the current store with the backup copy. This has a side effect of removing the current store from the Core Data stack.
55+ // When restoring, it's necessary to use the current persistent store coordinator.
56+ try persistentStoreCoordinator. replacePersistentStore ( at: loadedStoreURL, destinationOptions: storeOptions, withPersistentStoreFrom: backupStoreURL, sourceOptions: storeOptions, ofType: storeType)
57+ // Add the persistent store at the same location we've been using, because it was removed in the previous step.
58+ try persistentStoreCoordinator. addPersistentStore ( ofType: storeType, configurationName: configurationName, at: loadedStoreURL, options: storeOptions)
6459 } catch {
6560 throw CopyPersistentStoreErrors . copyStoreError ( " Could not restore: \( error. localizedDescription) " )
6661 }
@@ -102,24 +97,24 @@ extension NSPersistentContainer {
10297 throw CopyPersistentStoreErrors . destinationError ( " Could not create destination directory at \( destinationURL) " )
10398 }
10499
105-
106100 for persistentStoreDescription in persistentStoreDescriptions {
107101 guard let storeURL = persistentStoreDescription. url else {
108102 continue
109103 }
110104 guard persistentStoreDescription. type != NSInMemoryStoreType else {
111105 continue
112106 }
113- let temporaryPSC = NSPersistentStoreCoordinator ( managedObjectModel: persistentStoreCoordinator. managedObjectModel)
114107 let destinationStoreURL = destinationURL. appendingPathComponent ( storeURL. lastPathComponent)
115108
116109 if !overwriting && FileManager . default. fileExists ( atPath: destinationStoreURL. path) {
117- // If the destination exists, the migratePersistentStore call will update it in place. That's fine unless we're not overwriting.
110+ // If the destination exists, the replacePersistentStore call will update it in place. That's fine unless we're not overwriting.
118111 throw CopyPersistentStoreErrors . destinationError ( " Destination already exists at \( destinationStoreURL) " )
119112 }
120113 do {
121- let newStore = try temporaryPSC. addPersistentStore ( ofType: persistentStoreDescription. type, configurationName: persistentStoreDescription. configuration, at: persistentStoreDescription. url, options: persistentStoreDescription. options)
122- let _ = try temporaryPSC. migratePersistentStore ( newStore, to: destinationStoreURL, options: persistentStoreDescription. options, withType: persistentStoreDescription. type)
114+ // Replace an existing backup, if any, with a new one with the same options and type. This doesn't affect the current Core Data stack.
115+ // The function name says "replace", but it works if there's nothing at the destination yet. In that case it creates a new persistent store.
116+ // Note that for backup, it doesn't matter if the persistent store coordinator is the one currently in use or a different one. It could be a class function, for this use.
117+ try persistentStoreCoordinator. replacePersistentStore ( at: destinationStoreURL, destinationOptions: persistentStoreDescription. options, withPersistentStoreFrom: storeURL, sourceOptions: persistentStoreDescription. options, ofType: persistentStoreDescription. type)
123118 } catch {
124119 throw CopyPersistentStoreErrors . copyStoreError ( " \( error. localizedDescription) " )
125120 }
0 commit comments