В моем приложении на основе документов я столкнулся с некоторыми проблемами с переносом постоянного хранилища из папки "Приложения" в другое место в текущей выбранной пользователем папке.
(код упрощен)
Я инициализировал контекст объекта, подобный этому
_moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[_moc setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[_moc setPersistentStoreCoordinator:coordinator];
[_moc setUndoManager:[self undoManager]];
Я использую эти постоянные параметры хранилища
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
NSSQLitePragmasOption = {
"journal_mode" = DELETE;
};
И создать
store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:absoluteURL options:[options copy] error:error];
И местоположение этого постоянного хранилища - файл:///Users/currentuser/Library/Containers/com.my.application.osx/Data/Documents/doc1.ext
Затем я заполняю некоторые предпочтения
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
[[managedObjectContext undoManager] disableUndoRegistration];
NSEntityDescription *description = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = description;
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
Settings *file = nil;
if (error == nil) {
if ([results count]>0) {
file = [results firstObject];
} else {
file = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
}
[Settings setEntityFromUserDefaults:&file];
}
_fileSettings = file;
[managedObjectContext processPendingChanges];
[[managedObjectContext undoManager] enableUndoRegistration];
[self syncFileModificationDate];
И, наконец, когда я пытаюсь выполнить эту операцию
NSPersistentStoreCoordinator *coordinator = [self.managedObjectContext persistentStoreCoordinator];
[coordinator migratePersistentStore:[coordinator.persistentStores firstObject] toURL:absoluteURL options:[coordinator.persistentStores firstObject].options withType:NSSQLiteStoreType error:&error2];
Я что вижу в консоли отладки
2017-04-11 18: 09: 32.336 Проект [36495: 4118531] CoreData: ошибка: (21) Ошибка ввода-вывода для базы данных в /Users/dzawadsky/Documents/tmp author docs/doc1.ext. Код ошибки SQLite: 21, "невозможно открыть файл базы данных"
2017-04-11 18: 24: 42.980 Проект [36495: 4118531] CoreData: ошибка: - -addPersistentStoreWithType: конфигурация SQLite: PF_DEFAULT_CONFIGURATION_NAME URL: файл:///Пользователи /dzawadsky/Documents/tmp %20author %20docs/doc1. ext options: {
NSInferMappingModelAutomaticallyOption = 1; NSMigratePersistentStoresAutomaticallyOption = 1; NSPersistentStoreRemoveUbiquitousMetadataOption = 1; NSSQLitePragmasOption = { "journal_mode" = DELETE; };
}... возвращенная ошибка Ошибка домена = NSCocoaErrorDomain Code = 21 "(null)"
Код ошибки SQLite: 21, "невозможно открыть файл базы данных"} с помощью словаря userInfo {
NSSQLiteErrorDomain = 21; NSUnderlyingException = "I/O error for database at /Users/currentuser/Documents/tmp author docs/doc1.ext. SQLite error
код: 21, "невозможно открыть файл базы данных";
}
UPD
Я уже пытался пойти другим путем -
[fileManager copyItemAtURL:itemAtURL toURL:absoluteURL error:&error2];
и установить
[super setFileURL:absoluteURL];
Таким образом, постоянное хранилище контекста управляемого объекта было изменено, но когда я добавляю некоторые управляемые объекты в контекст и вызываю
[_moc save:&error];
Ошибка повторяется - это все та же ошибка, о которой я говорил ранее
Хотя вопрос довольно старый, я попытался проверить все, что хочет быть сохраненным в CoreData. Похоже, что в какой-то момент, в то время как спам-действие отменяется, система хочет сохранить объект с полями мусора (но у меня есть только один конструктор для этого объекта, который предотвращает создание таких значений полей). Пытался обнаружить место, где этот объект создается, безуспешно. Поэтому я запрещаю писать этот мусорный объект. Я сделал это, насколько я помню, используя какой-то селектор resetPending ManagedObjectContext, или smth вроде этого (не совсем - [moc reset], он очистит все данные в вашем MOC, будьте осторожны)!