Ios 本地备份核心数据,并从备份中恢复-Swift
我正在努力寻找有关创建核心数据备份的任何信息。我的最终目标是允许用户创建多个备份,并从选定的备份进行恢复 我发现了一个示例项目,它允许您在Objective-C中本地或通过iCloud进行备份/恢复,但在swift中没有Ios 本地备份核心数据,并从备份中恢复-Swift,ios,swift,core-data,backup,restore,Ios,Swift,Core Data,Backup,Restore,我正在努力寻找有关创建核心数据备份的任何信息。我的最终目标是允许用户创建多个备份,并从选定的备份进行恢复 我发现了一个示例项目,它允许您在Objective-C中本地或通过iCloud进行备份/恢复,但在swift中没有 有人能帮忙吗?或者给我指出正确的方向。我甚至不知道从哪里开始 我只需花两分钱就可以得到更多有价值的想法:为了解决这个问题,我会尝试使用CloudKit创建不同的客户区域,在iCloud中的应用程序用户的私有数据库中存储来自核心数据的不同备份。我从来都不需要这样做,但如果我这样做
有人能帮忙吗?或者给我指出正确的方向。我甚至不知道从哪里开始 我只需花两分钱就可以得到更多有价值的想法:为了解决这个问题,我会尝试使用CloudKit创建不同的客户区域,在iCloud中的应用程序用户的私有数据库中存储来自核心数据的不同备份。我从来都不需要这样做,但如果我这样做了,我会这么做 备份 在任何时候,请使用以下步骤:
NSPersistentContainer
或创建NSPersistentStoreCoordinator
的旧方法(但仍受支持)UserDefaults
或创建新的属性列表文件以保存备份信息NSPersistentContainer
,请使用其persistentStoreCoordinator
属性执行步骤2
从备份中恢复
这有点棘手,因为您的应用程序可能正在使用其持久存储,但现在您想用旧版本替换它从备份还原之前,请确保当前未使用永久存储中的任何托管对象。解除分配您的nspersistentcainer
。卸载使用托管对象的任何UI。让你的应用进入这样一种状态:它所能做的就是从备份中恢复,或者返回到使用当前数据的状态,但是除了备份列表之外,它不会显示任何数据
既然你这么做了
NSPersistentStoreCoordinator
replacePersistentStore(at:destinationOptions:withPersistentStoreFrom:sourceOptions:ofType:)
方法将备份数据复制到正常的应用程序位置。起始位置是备份位置,目标位置是应用程序通常保存其数据的位置NSPersistentStoreCoordinator
的函数destroyPersistentStore(位于:ofType:options:)
删除备份NSPersistentContainer
,然后重新加载常规应用程序UIFileManager
,来实现这些功能。核心数据方法将覆盖所有与核心数据相关的文件,并做其他好事,如避免造成数据损坏和遵守文件锁
更新:我后来写了一篇博客文章,详细介绍了这一点,并给出了示例代码:我在Tom的答案和苹果示例的帮助下创建了以下方法。 这将备份核心数据文件,并将其放置到所需的路径 斯威夫特5
///将存储类型备份到新的唯一位置
///下面的代码片段演示了该方法,其中显示了如何使用migratePersistentStore备份存储并将其从一个位置保存到另一个位置。
///如果旧的存储类型是XML,则示例还将该存储转换为SQLite。
///-参数:
///-路径:要在其中完成备份,请创建一个带有时间戳或guid的新唯一目录
///-完成:出错时通过错误,成功时通过零
类func backUpCoreDataFiles(路径:URL,完成:@escaping(u错误:String?)->())
{
//每次必须创建新容器时,migratePersistentStore方法都会在迁移时丢失对容器的引用
let container=NSPersistentContainer(名称:“”)
container.loadPersistentStores
中的{(storeDescription,错误)
如果let error=error
{
fatalError(“未能加载存储:\(错误)”)
}
}
let coordinator=container.persistentStoreCoordinator
let store=coordinator.persistentStores[0]
做
{
尝试coordinator.migratePersistentStore(store,to:path,options:nil,withType:NSSQLiteStoreType)
完成(无)
}
抓住
{
完成(\(Errors.coredataBackupError)\(error.localizedDescription))
}
}
详细信息
- Swift 5.1,Xcode 11.3.1
就这样。。希望这有帮助。谢谢你的建议。对我的应用程序来说,这一过程完全离线并且不依赖于CloudKit或iCloud是很重要的。所以我真的需要在本地存储。我相信这只是复制SQLLite文件并保存到位置的一个例子。恢复。抄回。但我不知道如何做到这一点。我没有离线备份的经验,但会研究将数据编码到本地文件并压缩文件,以间接满足您的目的,并使用Swift。为了直接备份和恢复SQLLite文件,我会查看标准库,但对Swift I的任何发现表示怀疑
/// 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)")
}
}
func backup(backupName: String){
let backUpFolderUrl = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first!
let backupUrl = backUpFolderUrl.appendingPathComponent(backupName + ".sqlite")
let container = NSPersistentContainer(name: "Your Project Name")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in })
let store:NSPersistentStore
store = container.persistentStoreCoordinator.persistentStores.last!
do {
try container.persistentStoreCoordinator.migratePersistentStore(store,to: backupUrl,options: nil,withType: NSSQLiteStoreType)
} catch {
print("Failed to migrate")
}
}
func restoreFromStore(backupName: String){
print(DatabaseHelper.shareInstance.getAllUsers())
let storeFolderUrl = FileManager.default.urls(for: .applicationSupportDirectory, in:.userDomainMask).first!
let storeUrl = storeFolderUrl.appendingPathComponent("YourProjectName.sqlite")
let backUpFolderUrl = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first!
let backupUrl = backUpFolderUrl.appendingPathComponent(backupName + ".sqlite")
let container = NSPersistentContainer(name: "YourProjectName")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
let stores = container.persistentStoreCoordinator.persistentStores
for store in stores {
print(store)
print(container)
}
do{
try container.persistentStoreCoordinator.replacePersistentStore(at: storeUrl,destinationOptions: nil,withPersistentStoreFrom: backupUrl,sourceOptions: nil,ofType: NSSQLiteStoreType)
print(DatabaseHelper.shareInstance.getAllUsers())
} catch {
print("Failed to restore")
}
})
}
self.backup(backupName: "first_backup")
self.restoreFromStore(backupName: "first_backup")