我目前正在使用NSPersistentDocument
子类,它使用NSOperation
在后台导入数据。根据文档,我在保存后台任务后观察NSManagedObjectContextDidSaveNotification
,并在主线程中使用-mergeChangesFromContextDidSaveNotification:
将通知传播到NSManagedObjectContext
。核心数据和NSOperation
一切工作正常,但它为将数据导入新文档的用户呈现了一个奇怪的工作流程。他们需要在导入之前保存一个空文档(否则-save:
失败,因为该文档没有配置NSPersistentStoreCoordinator
的URL)。除了某种“新文档设置”向导之外,我没有看到任何解决方法确保-writeToURL:ofType:forSaveOperation:originalContentsURL:error:
在导入之前被调用。
此外,似乎在后台导入任务排除在主线程上使用NSUndoManager
。 (我假设跨线程共享托管对象上下文的撤销管理器是不安全的。)从用户的角度来看,无法撤消在导入过程中创建的所有新对象。
我已经阅读了核心数据编程指南和Marcus Zarra的书,但我仍然对这个框架的这方面不熟悉。希望我忽略了一些事情:如果没有,我会使我的应用适应这些限制(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];
}
就像你在Mac上一样,你不能在内存存储中使用内存,然后在准备好时切换上下文以使用基于文件的存储?上面的方法也可以解决撤销问题,因为如果需要的话,你可以放弃整个上下文堆栈。似乎我在写这篇文章的时候大家写的都一样:) – Jonathan 2011-02-07 19:48:59