2011-02-07 3 views
5

В настоящее время я работаю с подклассом 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]; 
} 
+1

Как вы на Mac, не можете ли вы использовать хранилище в памяти, а затем переключить контекст, чтобы использовать хранилище на основе файлов, когда вы готовы? Вышеупомянутое также решит проблему с отменой, поскольку вы можете просто обойтись со всем стеком контекста, если это необходимо. Кажется, в то время как я писал, что все писали то же самое :) – Jonathan

ответ

5

Я - эксперт по основным данным ядра, но из того, что я могу сказать из документов, вы захотите начать с хранилища в памяти, пока пользователь (в свое время) не сохранит документ. Затем отправьте координатору a migratePersistentStore:toURL:options:withType:error: message, чтобы перейти из хранилища в память в новый по-настоящему постоянный магазин.См. Этот документ для некоторых существенных деталей (особенно в отношении судьбы магазина, в котором вы мигрируете).

+0

Спасибо, Питер! Миграция была частью головоломки, которая отсутствовала - я обновил свой пост выше. – chockenberry

2

Моя первая мысль на рабочий процесс/откладывая часть будет, если persisten t хранилище еще не создано для документа, чтобы создать временное хранилище в памяти, чтобы импортированные данные были сохранены в этом хранилище (хотя документ/окно по-прежнему будут помечены как грязные). Затем, как только пользователь сохранит документ на самом деле, вы переконфигурируете координатора для удаления хранилища в памяти и замените его хранилищем на диске, так что все последующие сохранения будут идти на диск.

0

Вы пытались настроить временный URL-адрес файла при настройке координатора? Вы должны иметь возможность отменить -mergeChangesFromContextDidSaveNotification: в основном потоке. Нет необходимости регистрировать менеджера отмены для MOC в фоновом потоке.

+0

Хорошее решение, как бы ни говорили Daniel, Питер и Брайан, просто создание магазина в памяти просто аккуратно и не говоря уже об ускорении. Однако это должно быть альтернативой, если говорить о очень большом наборе данных. – Jonathan

2

Я не на 100% знаком с материалом Mac, но я уверен, что вы могли бы использовать постоянное хранилище в памяти до того, как пользователь сохранил, а затем добавьте хранилище sql/plist после этого действия.

Потенциально даже лучше было бы создать постоянное хранилище на диске в стандартном временном каталоге и переместить его, когда пользователь нажмет на сохранение.

Смежные вопросы