Если кому-то нужно быстрое решение, просто добавьте функцию в didFinishLaunchingWithOptions.
func migratePersistentStore(){
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
var storeOptions = [AnyHashable : Any]()
storeOptions[NSMigratePersistentStoresAutomaticallyOption] = true
storeOptions[NSInferMappingModelAutomaticallyOption] = true
let oldStoreUrl = self.applicationDocumentsDirectory.appendingPathComponent("YourApp.sqlite")!
let newStoreUrl = self.applicationGroupDirectory.appendingPathComponent("YourApp.sqlite")!
var targetUrl : URL? = nil
var needMigrate = false
var needDeleteOld = false
if FileManager.default.fileExists(atPath: oldStoreUrl.path){
needMigrate = true
targetUrl = oldStoreUrl
}
if FileManager.default.fileExists(atPath: newStoreUrl.path){
needMigrate = false
targetUrl = newStoreUrl
if FileManager.default.fileExists(atPath: oldStoreUrl.path){
needDeleteOld = true
}
}
if targetUrl == nil {
targetUrl = newStoreUrl
}
if needMigrate {
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: targetUrl!, options: storeOptions)
if let store = coordinator.persistentStore(for: targetUrl!)
{
do {
try coordinator.migratePersistentStore(store, to: newStoreUrl, options: storeOptions, withType: NSSQLiteStoreType)
} catch let error {
print("migrate failed with error : \(error)")
}
}
} catch let error {
CrashlyticsHelper.reportCrash(err: error as NSError, strMethodName: "migrateStore")
}
}
if needDeleteOld {
DBHelper.deleteDocumentAtUrl(url: oldStoreUrl)
guard let shmDocumentUrl = self.applicationDocumentsDirectory.appendingPathComponent("NoddApp.sqlite-shm") else { return }
DBHelper.deleteDocumentAtUrl(url: shmDocumentUrl)
guard let walDocumentUrl = self.applicationDocumentsDirectory.appendingPathComponent("NoddApp.sqlite-wal") else { return }
DBHelper.deleteDocumentAtUrl(url: walDocumentUrl)
}
}
Мой PersistentStoreCoordinator выглядит так:
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationGroupDirectory.appendingPathComponent("YourApp.sqlite")
var storeOptions = [AnyHashable : Any]()
storeOptions[NSMigratePersistentStoresAutomaticallyOption] = true
storeOptions[NSInferMappingModelAutomaticallyOption] = true
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options:storeOptions)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
Это тот случай, когда в магазине приложений уже есть приложение, и вы хотите перенести файл постоянного хранилища coreData из расположения магазина по умолчанию в расположение группы приложений.
Изменить. Для удаления файла из старого местоположения рекомендуется использовать NSFileCoordinator для выполнения задачи.
static func deleteDocumentAtUrl(url: URL){
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
fileCoordinator.coordinate(writingItemAt: url, options: .forDeleting, error: nil, byAccessor: {
(urlForModifying) -> Void in
do {
try FileManager.default.removeItem(at: urlForModifying)
}catch let error {
print("Failed to remove item with error: \(error.localizedDescription)")
}
})
}
Обратите внимание, что причина, по которой NSFileCoordinator используется для удаления файла, заключается в том, что NSFileCoordinator позволяет нам гарантировать, что задачи, связанные с файлом, такие как открытие чтения и записи, выполняются таким образом, чтобы не мешать любой другой задаче в системе, пытающейся работать с тем же файлом. Например, если вы хотите открыть файл и в то же время удалить его, вы не хотите, чтобы оба действия выполнялись одновременно.
Пожалуйста, вызовите вышеуказанную функцию после того, как хранилище будет успешно перенесено.
person
Pranav Gupta
schedule
29.11.2017