我很难找到有关创建核心数据备份的任何信息。我的最终目标是允许用户创建多个备份,并从选定的备份进行还原。
我找到了一个示例项目,允许您在本地或通过Objective-C中的iCloud进行备份/恢复,但没有什么在swift中。
有人可以帮忙吗?或者指出我正确的方向。我甚至不知道从哪里开始。
答案 0 :(得分:15)
我从来不需要这样做,但如果我这样做,那就是我要做的事。
任何时候,请使用以下步骤:
InputDecoration
或较旧(但仍受支持)的方法创建NSPersistentContainer
。NSPersistentStoreCoordinator
的函数NSPersistentStoreCoordinator
创建备份。使用UUID或时间戳使目标URL包含唯一的内容。将备份放在文档文件夹中。migratePersistentStore(_:to:options:withType:)
中或创建新的属性列表文件以保存备份信息。步骤#2将从Core Data堆栈中删除原始存储 - 这就是您在步骤#1中创建第二个堆栈的原因。这样,您可以使用第二个堆栈进行备份,而不会影响您的应用正在使用的备份。
如果您使用的是UserDefaults
,请使用其NSPersistentContainer
属性执行第2步。
这有点棘手,因为您的应用可能正在使用其持久性存储,但现在您想用旧版本替换它。 从备份恢复之前,请确保您当前没有使用持久存储中的任何托管对象。取消分配您的persistentStoreCoordinator
。卸载任何使用托管对象的UI。让您的应用程序进入一种状态,它可以做的就是从备份恢复或返回使用当前数据,但除了备份列表之外它没有显示任何数据。
现在你已经完成了,
NSPersistentContainer
。NSPersistentStoreCoordinator
方法将备份数据复制到普通的应用位置。起始位置是备份位置,目标是应用程序通常保存其数据的位置。replacePersistentStore(at:destinationOptions:withPersistentStoreFrom:sourceOptions:ofType:)
的函数NSPersistentStoreCoordinator
删除备份。destroyPersistentStore(at:ofType:options:)
并重新加载常规应用UI。不要将NSPersistentContainer
之类的直接文件相关API用于此任何一项。核心数据方法将涵盖所有与核心数据相关的文件,并做其他好事,例如避免导致数据损坏和尊重文件锁。
答案 1 :(得分:3)
yourhost/api/-default-/public/alfresco/versions/1/nodes/{{uiid}
就是这样!
现在
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")
}
})
}
就是这样。希望这对您有所帮助。谢谢
答案 2 :(得分:0)
为了更有价值的想法,我只需花两分钱:为了解决这个问题,我会尝试使用CloudKit创建不同的客户区域,以便在核心数据的iCloud中的App用户私有数据库中存储不同的备份。
答案 3 :(得分:0)
我在汤姆的答案和Apple示例code的帮助下创建了以下方法。 这将备份核心数据文件,并将其放置到所需的路径。
雨燕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)")
}
}