Как принудительно создать постоянное хранилище/автосохранение по умолчанию в NSPersistentDocument

У меня есть приложение Cocoa на основе документов, использующее CoreData, которое может импортировать большие объемы данных. Поскольку этот импорт занимает некоторое время, я делаю это в фоновом режиме, но поскольку NSManagedObjectContext не является сохранением потока, я использовал persistentStoreCoordinator из managedObjectContext документа для создания нового NSManagedObjectContext в фоновом потоке. Теперь, когда импорт завершен, я сохраняю фон managedObjectContext, чтобы уведомить основной поток документа managedObjectContext об изменениях и объединить их. Насколько я понимаю, именно так должен выполняться параллелизм с использованием CoreData.

Но иногда у persistentStoreCoordinator нет persistentStore, когда я вызываю [managedObjectContex save:], что приводит к сбою сохранения и сбою приложения. Я использую автосохранение и все такое (в основном немодифицированный NSPersistentDocument в OS X 10.8), поэтому я предположил, что мне не нужно заботиться о том, как он сохраняется, и он будет «просто работать».

Судя по всему, это не так. Я попытался форсировать операцию автосохранения, надеясь, что это создаст persistenceStore, вызвав [self autosaveDocumentWithDelegate:self didAutosaveSelector:@selector(document:didAutosave:contextInfo:) contextInfo:nil]; в конце windowControllerDidLoadNib: в моем подклассе документа, но, похоже, это ничего не меняет. Обратный вызов делегата (- (void)document:(NSDocument *)document didAutosave:(BOOL)didAutosaveSuccessfully contextInfo:(void *)contextInfo) фактически указывает, что автосохранение было успешным, хотя ни один из файловых URL-адресов или связанных методов доступа не возвращает что-то отличное от нуля, и не было создано persistingStore.

Я также подумал о том, чтобы самому вызвать -(BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError *__autoreleasing *)error, но я не знаю, какой URL использовать, чтобы он работал как обычное автосохранение. Я проверил backupFileURL, fileURL и autosavedContentsFileURL, но все они по-прежнему равны нулю в конце windowControllerDidLoadNib:. На самом деле они равны нулю даже после того, как были вызваны writeToURL:... и configurePersistentStoreCoordinatorForURL:..., поэтому я понятия не имею, как получить "правильный" URL.

Чтобы лучше понять, как и когда создается постоянное хранилище, я установил контрольные точки в writeToURL:... и configurePersistentStoreCoordinatorForURL:.... Я заметил, что configurePersistentStoreCoordinatorForURL: вызывается, когда приложение теряет самый передний статус. Но когда я просто создаю новый документ и пытаюсь импортировать что-то сразу после его создания (без предварительного переключения на другое приложение, чтобы вызвать создание постоянного хранилища), он падает. Если я переключаюсь на другое приложение, магазин создается и все работает нормально. Кстати, URL-адрес, используемый для созданного таким образом постоянного хранилища, всегда находится где-то во временном каталоге.

Я делаю что-то неправильно? Разве мне не нужно вызывать [managedObjectContext save:], чтобы уведомить другой ManagedObjectContext об изменениях? Как я могу заставить документ создать свое временное хранилище? Почему вызов autosaveDocumentWithDelegate:... фактически не сохраняет документ (и, таким образом, не создает persistentStore)?

Связанный:


person Joachim Kurz    schedule 10.01.2013    source источник


Ответы (1)


Я решил аналогичную проблему: мне нужно сгенерировать постоянные идентификаторы объектов, для которых требуется наличие постоянного хранилища. Как вы заметили, документы без названия, которые еще не были автоматически сохранены, не имеют постоянных хранилищ.

Этот сокращенный фрагмент из моего подкласса NSWindowController:

- (void) awakeFromNib {
    //hacky way to get an autosave to generate an NSPersistentStore.
    GSNativeDocument *doc = self.document;
    [doc updateChangeCount:NSChangeDone];
    [doc autosaveDocumentWithDelegate:self didAutosaveSelector:@selector(document:didAutosave:contextInfo:) contextInfo:nil];
}

//called by the autosave operation started in awakeFromNib.
- (void)document:(NSDocument *)document didAutosave:(BOOL)didAutosaveSuccessfully contextInfo:(void *)contextInfo
{
    GSNativeDocument *doc = self.document;
    [doc updateChangeCount:NSChangeUndone];
}

Почему обновление счетчика изменений создает «настоящее» автосохранение, а любой другой способ вызвать автосохранение — нет? Я понятия не имею. Я сообщил об этой ошибке в Apple в начале января и разместил сообщение на форумах разработчиков, но они не ответили.

person Khakionion    schedule 01.02.2013
comment
Я должен указать, я уверен, что это следует рассматривать как ошибку, потому что это приводит к непоследовательному поведению (автосохраненные документы, которые приложение будет восстанавливать при запуске, но без URL-адресов или постоянных хранилищ, к которым может получить доступ разработчик). Я зарегистрировал его в Apple как rdar://problem/12970136, так что посмотрим, получится ли из этого что-нибудь. - person Khakionion; 04.02.2013