В настоящее время я работаю с подклассом NSPersistentDocument
, который использует NSOperation
для импорта данных в фоновом режиме. Согласно документации, я наблюдаю NSManagedObjectContextDidSaveNotification
после сохранения в фоновом режиме и распространения уведомления в NSManagedObjectContext
в основном потоке, используя -mergeChangesFromContextDidSaveNotification:
.
Все работает отлично, но представляет странный рабочий процесс для пользователя, который импортирует данные в новый документ. Им необходимо сохранить пустой документ перед выполнением импорта (в противном случае -save:
завершится неудачей, поскольку в документе не настроен URL-адрес для NSPersistentStoreCoordinator
.) Я не вижу способа обойти это, кроме какого-то «нового» мастер настройки документа, обеспечивающий вызов -writeToURL:ofType:forSaveOperation:originalContentsURL:error:
перед импортом.
Кроме того, похоже, что задача импорта в фоновом режиме исключает использование NSUndoManager
в главном потоке. (Я предполагаю, что небезопасно разделять диспетчер отмены контекста управляемого объекта между потоками.) С точки зрения пользователя, невозможно отменить все новые объекты, созданные во время импорта.
Я прочитал и Руководство по программированию основных данных , и книгу Маркуса Зарры, но я все еще новичок в этом аспекте фреймворка. Надеюсь, я что-то упустил: если нет, я адаптирую свое приложение к этим ограничениям (преимущества Core Data намного перевешивают эти ограничения пользовательского интерфейса.)
Спасибо за ваше время!
-
Основываясь на предложении Питера Хоси, приведенном ниже, я добавил следующий код для создания временного постоянного хранилища перед импортом:
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];
}