В настоящее время я работаю с подклассом NSPersistentDocument
, который использует NSOperation
для импорта данных в фоновом режиме. В соответствии с документацией я наблюдаю за NSManagedObjectContextDidSaveNotification
после сохранения в фоновом задании и распространения уведомления на NSManagedObjectContext
в основной теме с использованием -mergeChangesFromContextDidSaveNotification:
.Основные данные и NSOperation
Все работает нормально, но представляет собой странный рабочий процесс для пользователя, который импортирует данные в новый документ. Им нужно сохранить пустой документ перед выполнением импорта (в противном случае -save:
завершится с ошибкой, потому что документ не настроил URL-адрес для NSPersistentStoreCoordinator
.) Я не вижу пути вокруг этого другого, кроме какого-то мастера настройки «нового документа» который обеспечивает вызов -writeToURL:ofType:forSaveOperation:originalContentsURL:error:
до вызова.
Также представляется, что задача импорта в фоновом режиме исключает использование NSUndoManager
в основном потоке. (Я предполагаю, что небезопасно делиться менеджером отмены контекста управляемого объекта по потокам.) С точки зрения пользователя нет возможности отменить все новые объекты, созданные во время импорта.
Я читал как Руководство по программированию основных данных, так и книгу Маркуса Зарры, но я все еще новичок в этом аспекте структуры. Надеюсь, я кое-что упустил: если нет, я адаптирую свое приложение к этим ограничениям (преимущества Core Data намного превосходят эти ограничения для пользовательского интерфейса.)
Спасибо за ваше время!
-
Основываясь на предложении Питера Hosey в поле ниже, я добавил следующий код, чтобы создать временное постоянное хранилище до импорта:
NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator];
if ([[persistentStoreCoordinator persistentStores] count] == 0) {
// create an in-memory store to use temporarily
NSError *error;
NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:&error];
if (! persistentStore) {
NSLog(@"error = %@", error); // TODO: better error handling
}
}
Затем, после того, как файл выбран в сохранении панель, временный настойчивый магазин переносится в SQLite хранилище в выбранном URL:
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:(NSError **)error
{
NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator];
for (NSPersistentStore *persistentStore in [persistentStoreCoordinator persistentStores]) {
if (persistentStore.type == NSInMemoryStoreType) {
// migrate the in-memory store to a SQLite store
NSError *error;
NSPersistentStore *newPersistentStore = [persistentStoreCoordinator migratePersistentStore:persistentStore toURL:absoluteURL options:nil withType:NSSQLiteStoreType error:&error];
if (! newPersistentStore) {
NSLog(@"error = %@", error); // TODO: better error handling
}
}
}
return [super writeToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation originalContentsURL:absoluteOriginalContentsURL error:error];
}
Как вы на Mac, не можете ли вы использовать хранилище в памяти, а затем переключить контекст, чтобы использовать хранилище на основе файлов, когда вы готовы? Вышеупомянутое также решит проблему с отменой, поскольку вы можете просто обойтись со всем стеком контекста, если это необходимо. Кажется, в то время как я писал, что все писали то же самое :) – Jonathan