Основные данные и NSOperation - PullRequest
5 голосов
/ 07 февраля 2011

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

Ответы [ 4 ]

5 голосов
/ 07 февраля 2011

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

2 голосов
/ 07 февраля 2011

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

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

2 голосов
/ 07 февраля 2011

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

0 голосов
/ 07 февраля 2011

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

...