@@ -38,29 +38,24 @@ extension NSPersistentContainer {
38
38
throw CopyPersistentStoreErrors . invalidSource ( " Source URL must exist " )
39
39
}
40
40
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 {
43
43
continue
44
44
}
45
45
let backupStoreURL = backupURL. appendingPathComponent ( loadedStoreURL. lastPathComponent)
46
46
guard FileManager . default. fileExists ( atPath: backupStoreURL. path) else {
47
47
throw CopyPersistentStoreErrors . invalidSource ( " Missing backup store for \( backupStoreURL) " )
48
48
}
49
49
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)
64
59
} catch {
65
60
throw CopyPersistentStoreErrors . copyStoreError ( " Could not restore: \( error. localizedDescription) " )
66
61
}
@@ -102,24 +97,24 @@ extension NSPersistentContainer {
102
97
throw CopyPersistentStoreErrors . destinationError ( " Could not create destination directory at \( destinationURL) " )
103
98
}
104
99
105
-
106
100
for persistentStoreDescription in persistentStoreDescriptions {
107
101
guard let storeURL = persistentStoreDescription. url else {
108
102
continue
109
103
}
110
104
guard persistentStoreDescription. type != NSInMemoryStoreType else {
111
105
continue
112
106
}
113
- let temporaryPSC = NSPersistentStoreCoordinator ( managedObjectModel: persistentStoreCoordinator. managedObjectModel)
114
107
let destinationStoreURL = destinationURL. appendingPathComponent ( storeURL. lastPathComponent)
115
108
116
109
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.
118
111
throw CopyPersistentStoreErrors . destinationError ( " Destination already exists at \( destinationStoreURL) " )
119
112
}
120
113
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)
123
118
} catch {
124
119
throw CopyPersistentStoreErrors . copyStoreError ( " \( error. localizedDescription) " )
125
120
}
0 commit comments