问题
I'm struggling to find any information about creating backups of core data. My ultimate goal is to allow the user to create multiple backups, and restore from a selected backup.
I've found a sample project that allows you backup/restore locally or via iCloud in Objective-C, but nothing in swift.
Can anyone help? Or point me in the right direction. I don't even know where to start with this one.
回答1:
I've never needed to do this but if I did this is what I'd do.
To make backups
At any time, use the following steps:
- Create a new, second Core Data stack. Use either
NSPersistentContaineror the older (but still supported) method of creating anNSPersistentStoreCoordinator. - Use
NSPersistentStoreCoordinator's functionmigratePersistentStore(_:to:options:withType:)to create the backup. Make the destination URL include something unique, using a UUID or a timestamp. Put the backups in the documents folder. - Keep a list of backups by date. You could put this in
UserDefaultsor create a new property list file to save backup info.
Step #2 will remove the original store from the Core Data stack-- which is why you create a second stack in step #1. This way you can use the second stack to make the backup without affecting the one your app is using.
If you're using NSPersistentContainer, use its persistentStoreCoordinator property to carry out step #2.
To restore from backups
This is a little bit tricky because your app may be using its persistent store, but now you want to replace that with an older version. Before restoring from a backup, make sure you're not currently using any managed objects from the persistent store. Deallocate your NSPersistentContainer. Unload any UI that makes use of managed objects. Get your app into a state where all it can do is either restore from a backup or go back to using the current data, but where it's not showing any data except the backup list.
Now that you've done that,
- Display the backup list and let the user select one.
- Create an
NSPersistentStoreCoordinatorusing your data model. - Use the
replacePersistentStore(at:destinationOptions:withPersistentStoreFrom:sourceOptions:ofType:)method to copy the backup data to the normal app location. The starting location is the backup location, the destination is where the app normally saves its data. - (optional) Use
NSPersistentStoreCoordinator's functiondestroyPersistentStore(at:ofType:options:)to delete the backup. - Load an
NSPersistentContaineras usual and reload the regular app UI.
Don't use direct file-related APIs like FileManager for any of this. The Core Data methods will cover all of the Core Data-related files and do other nice things like avoid causing data corruption and respecting file locks.
回答2:
Just my two cents for more valuable thoughts: to tackle the problem, I would try to use CloudKit to create different customer zones to store different backups in the App user’s private database in iCloud from core data.
回答3:
I created the following method with the help of Tom's answer and the Apple sample code. This will take a backup of core data files and place it to the path that you want.
Swift 5
/// Backing up store type to a new and unique location
/// The method is illustrated in the following code fragment, which shows how you can use migratePersistentStore to take a back up of a store and save it from one location to another.
/// If the old store type is XML, the example also converts the store to SQLite.
/// - Parameters:
/// - path: Where you want the backup to be done, please create a new unique directory with timestamp or the guid
/// - completion: Passes error in case of error or pass nil in case of success
class func backUpCoreDataFiles(path : URL, completion : @escaping (_ error : String?) -> ())
{
// Every time new container is a must as migratePersistentStore method will loose the reference to the container on migration
let container = NSPersistentContainer(name : "<YourDataModelName>")
container.loadPersistentStores
{ (storeDescription, error) in
if let error = error
{
fatalError("Failed to load store: \(error)")
}
}
let coordinator = container.persistentStoreCoordinator
let store = coordinator.persistentStores[0]
do
{
try coordinator.migratePersistentStore(store, to : path, options : nil, withType : NSSQLiteStoreType)
completion(nil)
}
catch
{
completion("\(Errors.coredataBackupError)\(error.localizedDescription)")
}
}
来源:https://stackoverflow.com/questions/48613271/backup-core-data-locally-and-restore-from-backup-swift