我有一个 NSPersistentDocument 子类,它使用 NSManagedObject 子类来存储我的数据。
当打开一个新文档时,我会对数据结构进行一些初始化(填充字段的数量很少)。我注意到的是 Untitled 文档被自动保存,当应用程序重新打开时,该文档被加载。如果应用程序退出,用户不会(默认情况下)收到保存对话框的提示。如果窗口关闭,则用户关闭。
第一个问题:
我想在用户退出应用程序时调用保存对话框。我不希望这个无标题的文档到处乱跑(在正常情况下)。我要么希望它保存或丢弃。
我试图填写:
- (void)applicationWillTerminate:(NSNotification *)aNotification
为了触发要保存的文档。此时调用save:
上下文会出错。据我所知,这是因为用户还没有自己保存文件。此外,调用[self close];
或[[self windowForSheet] close];
关闭窗口而不保存。
如何强制弹出保存对话框?如何删除未命名的文档?
第二个问题(不,我数不清):
因为当应用程序启动时,可能有也可能没有 Untitled 文档要处理,所以我试图跟踪另一个模型中的状态。我已经发现,当 Untitled 文档出现时,初始数据(我之前提到的)已经存在。我的另一个模型有一些元数据,包括填充数据的成功标志/状态。一旦填充的数据全部到位并正确,状态就会显示为这样。不幸的是,虽然当应用程序以预先存在的无标题文档启动时加载了我的填充数据,但元数据类不是。
请原谅代码的粗糙,在这一点上,我正在修改它,直到我可以看到它在我修改它之前可以按照我想要的方式工作:
- (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:
在任何地方打电话。我依赖于标准的自动保存,或者用户执行保存。
编辑:
我安装了核心数据编辑器应用程序。事实证明,问题不在于保存数据,而在于加载数据。(注意:由于另一个问题,应用程序在指示另存为 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
. 在这个新项目中,上面的代码有效。