У меня есть подкласс NSPersistentDocument, использующий подклассы NSManagedObject для моих данных.
Когда открывается новый документ, я выполняю некоторую инициализацию структур данных (тривиальное количество заполненных полей). Я заметил, что документ без названия автоматически сохраняется, и при повторном открытии приложения этот документ загружается. Если приложение закрывается, пользователю не (по умолчанию) не предлагается диалоговое окно сохранения. Если окно закрывается, пользователь делает.
Первый вопрос:
Я хочу вызвать диалоговое окно сохранения, когда пользователь выходит из приложения. Я не хочу, чтобы этот документ без названия оставался без присмотра (при нормальных обстоятельствах). Я либо хочу, чтобы это было сохранено, либо уничтожено.
Я попытался заполнить:
- (void)applicationWillTerminate:(NSNotification *)aNotification
Чтобы активировать документ для сохранения. Вызов save:
для контекста в этот момент дает ошибку. Из того, что я могу сказать, это потому, что пользователь еще не сохранил файл самостоятельно. Кроме того, вызов [self close];
или [[self windowForSheet] close];
закрывает окно без сохранения.
Как заставить диалог сохранения появиться? Как я могу удалить документ без названия?
Второй вопрос (нет, я не могу сосчитать):
Поскольку при запуске приложения может существовать или не иметься документ без названия, я пытаюсь отслеживать состояние в другой модели. Я уже обнаружил, что исходные данные (на которые я ссылался ранее) присутствуют при появлении документа без названия. Моя другая модель имеет некоторые метаданные, включая флаг / состояние успеха для заполненных данных. Как только заполненные данные все на месте и исправлены, состояние указывается как таковое. К сожалению, хотя мои заполненные данные загружаются, когда приложение запускается с уже существующим документом без названия, класс метаданных - нет.
Прошу прощения за грубость кода, на данный момент я все испортил до тех пор, пока не увижу, что он работает так, как я хочу, прежде чем отполировать его обратно:
- (bool) createGameState {
NSEntityDescription* description = [NSEntityDescription entityForName:[GameState name] inManagedObjectContext:[self managedObjectContext]];
NSFetchRequest* req = [[NSFetchRequest alloc] init];
[req setEntity:description];
NSError *error = nil;
NSArray *array = [[self managedObjectContext] executeFetchRequest:req error:&error];
[req release];
req = nil;
GameState* result = nil;
if (array) {
NSUInteger count = [array count];
if (!count) {
// Create the new GameState.
DebugLog(@"Creating GameState");
result = [NSEntityDescription insertNewObjectForEntityForName:[GameState name] inManagedObjectContext:[self managedObjectContext]];
[result setIsLoaded:[NSNumber numberWithBool:NO]];
} else {
if (count > 1) {
NSLog(@"WARNING: Potentially Corrupt Game State. found: %lu", count);
}
result = [array objectAtIndex:0];
if ([result isLoaded]) {
[self variantLoaded];
} else {
// In this case, we have an aborted set-up. Since the game isn't
// playable, just refuse to create the GameState. This will
// force the user to create a new game.
return NO;
}
}
} else {
DebugLog(@"error: %@", error);
}
[game setState:result];
return result;
}
Обратите внимание, что массив всегда присутствует, а число всегда равно нулю. Нет, я нигде явно не звоню save:
. Я полагаюсь на стандартное автосохранение или на пользователя, выполняющего сохранение.
EDIT:
Я установил приложение Core Data Editor. Оказывается, проблема не в сохранении данных, а в их загрузке. (Примечание: из-за другой проблемы приложение сохраняет как двоичный файл, когда ему поручено сохранить как XML, что вызывает сильные удары головой.)
Я разбил его на простейший код, который должен собирать все объекты типа GameState в массиве. Он не получает ничего, несмотря на то, что в сохраненном файле явно присутствуют объекты соответствующего типа:
NSManagedObjectContext* moc = [self managedObjectContext];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"GameState" inManagedObjectContext:moc];
NSFetchRequest* req = [[NSFetchRequest alloc] init];
[req setEntity:entity];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:req error:&error];
Массив не равен нулю, но [array count]
равен 0.
На данный момент, я думаю, это что-то простое, что я пропускаю.
Второе редактирование:
Я добавил -com.apple.CoreData.SQLDebug 5
и сохранил как SQLite. Вызов executeFetchRequest
не генерирует журналы отладки. Я вижу запись INSERT INTO ZGAMESTATE
в журналах. Кажется, что executeFetchRequest
не передается бэкэнду.
Третий РЕДАКТИРОВАТЬ (этот горит):
Я создал новый проект xcode, используя базовые данные (как и в случае с другими). Я скопировал только одну эту функцию (заглушка там, где это необходимо) и добавил вызов к ней в windowControllerDidLoadNib
. В этом новом проекте код выше работает.