gpt4 book ai didi

ios - 核心数据。如何交换 NSPersistentStores 并通知 NSFetchedResultsController?

转载 作者:行者123 更新时间:2023-11-30 11:26:55 35 4
gpt4 key购买 nike

我正在(通过 Dropbox)实现用户的Core Data 持久数据的备份和恢复。为了进行恢复,我从 Dropbox 中提取文件并将它们临时存储在 Documents 目录中。然后,我创建一个新的 NSPercientContainer 并用它来替换当前的持久存储(在 ApplicationSupport 目录中),然后再删除 Documents 目录中不再需要的文件。

我现在使用 MasterDetail 模板,因此我有通常的时间戳实体和随之而来的 NSFetchedResultsController 。进行替换后,我切换回主 tableView,不幸的是看到了原始的实体集。当应用重新启动时,我按预期看到恢复的数据,但需要弄清楚如何使NSFetchedResultsController自动看到新恢复的数据。

这是我的恢复代码:

func restorePSFromBackup() {
// Current persistent store is in the ApplicationSupport directory.
let currentPSFolderUrl = FileManager.default.urls(for: .applicationSupportDirectory, in:.userDomainMask).first!
// The current Core Data file (url).
let currentPSUrl1 = currentPSFolderUrl.appendingPathComponent("DBCDTest.sqlite")
// Backup persistent store with which to restore is in the Documents directory.
let backUpFolderUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// The 3 backup Core Data files (urls).
let backupUrl1 = backUpFolderUrl.appendingPathComponent("DBCDTest.sqlite")
let backupUrl2 = backUpFolderUrl.appendingPathComponent("DBCDTest.sqlite-wal")
let backupUrl3 = backUpFolderUrl.appendingPathComponent("DBCDTest.sqlite-shm")
let sourceSqliteURLs = [backupUrl1, backupUrl2, backupUrl3]

let container = NSPersistentContainer(name: "DBCDTest")

do {
// Replace current persistent store with the restore/backup persistent store.
try container.persistentStoreCoordinator.replacePersistentStore(at: currentPSUrl1, destinationOptions: nil, withPersistentStoreFrom: backupUrl1, sourceOptions: nil, ofType: NSSQLiteStoreType)
// Delete the restore/backup files from the Application directory.
do {
for index in 0..<sourceSqliteURLs.count {
try FileManager.default.removeItem(at: sourceSqliteURLs[index])
}
} catch let error {
print("Failed to delete sqlite files.")
print(error.localizedDescription)
}
} catch let error {
print("Failed to replace persistent store.")
print(error.localizedDescription)
}
}

我尝试使用依赖注入(inject)来引用在 AppDelegate 中创建的容器,并使用它来执行交换,但尝试替换持久存储失败,而不是创建一个新的 NSPercientContainer。这可能是某种 NSManagedObjectContext 问题吗?在访问新数据存储之前是否需要刷新?

最佳答案

我设法从许多类似问题的答案中汇总出一个答案,特别是 Tom Harrington 中的这个答案。 。简而言之,我需要做的是:

  1. 创建一个新的 NSPercientContainer
  2. 使用 persistentStoreCoordinator 上的 replacePersistentStore 方法将当前持久存储替换为恢复/备份持久存储。
  3. 销毁备份存储。
  4. 删除与备份存储关联的文件。
  5. AppDelegate 中重建 Core Data 堆栈。
  6. 保存、nil,然后重新初始化 MasterViewController 的 managementObjectContextNSFetchedResultsController

6号花了一些时间让我看到曙光。我最终的恢复方法是:

func restorePSFromBackup() {
// Current persistent store is in the ApplicationSupport directory.
let currentPSFolderUrl = FileManager.default.urls(for: .applicationSupportDirectory, in:.userDomainMask).first!
// The current Core Data file (url).
let currentPSUrl1 = currentPSFolderUrl.appendingPathComponent("DBCDTest.sqlite")
// Backup persistent store with which to restore is in the Documents directory.
let backUpFolderUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// The 3 backup Core Data files (urls).
let backupUrl1 = backUpFolderUrl.appendingPathComponent("DBCDTest.sqlite")
let backupUrl2 = backUpFolderUrl.appendingPathComponent("DBCDTest.sqlite-wal")
let backupUrl3 = backUpFolderUrl.appendingPathComponent("DBCDTest.sqlite-shm")
let sourceSqliteURLs = [backupUrl1, backupUrl2, backupUrl3]

let container = NSPersistentContainer(name: "DBCDTest")

do {
// Replace current persistent store with the restore/backup persistent store.
try container.persistentStoreCoordinator.replacePersistentStore(at: currentPSUrl1, destinationOptions: nil, withPersistentStoreFrom: backupUrl1, sourceOptions: nil, ofType: NSSQLiteStoreType)
// Destroy the backup store.
try container.persistentStoreCoordinator.destroyPersistentStore(at: backupUrl1, ofType: NSSQLiteStoreType, options: nil)
// Delete the restore/backup files from the Application directory.
do {
for index in 0..<sourceSqliteURLs.count {
try FileManager.default.removeItem(at: sourceSqliteURLs[index])
}
} catch let error {
print("Failed to delete sqlite files.")
print(error.localizedDescription)
}
// Rebuild the AppDelegate's Core Data stack.
(UIApplication.shared.delegate as! AppDelegate).persistentContainer = NSPersistentContainer(name: "DBCDTest")
(UIApplication.shared.delegate as! AppDelegate).persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in
print(NSPersistentContainer.defaultDirectoryURL())
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
} else {
// Save, nil and then reinitialise the MasterViewController managedObjectContext and NSFetchedResultsController.
do {
try self.masterViewController.managedObjectContext?.save()
} catch let error {
print("Failed to save managedObjectContext.")
print(error.localizedDescription)
}
self.masterViewController.managedObjectContext = nil
self.masterViewController.managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
self.masterViewController._fetchedResultsController = nil
let _ = self.masterViewController.fetchedResultsController
}
})
} catch let error {
print("Failed to replace persistent store.")
print(error.localizedDescription)
}
}

关于ios - 核心数据。如何交换 NSPersistentStores 并通知 NSFetchedResultsController?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50647579/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com