Я выполняю резервное копирование и восстановление (через Dropbox) Core Data
сохраненных данных пользователя. Для восстановления я извлекаю файлы из Dropbox и временно сохраняю их в каталоге «Документы». Затем я создаю новый NSPersistentContainer
и использую его для замены текущего постоянного хранилища (в каталоге 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)
}
}
Вместо создания нового NSPersistentContainer
я попытался использовать внедрение зависимостей, чтобы сослаться на тот, который был создан в AppDelegate, и использовать его для выполнения свопа, но попытка заменить постоянные хранилища не удалась. Может быть, это какая-то проблема NSManagedObjectContext
? Может ли он нуждаться в очистке перед доступом к новому хранилищу данных?