0

我完全坚持这个。我的基本问题是我的:

   - (NSFetchedResultsController *)fetchedResultsController

方法在尝试读取我的核心核心实体时崩溃,因为 managedObjectContext / UIManagedDocument 为零。目前我认为这是因为我的 UIManagedDocument 没有打开/准备好。所以在过去的 3 个小时里,我一直在努力做到这一点,以便在文档打开之前不会触发我的委托方法。

这是我用来获取文档的代码:

      if (!self.document) {
    [[CATManagedDocumentHandler sharedDocumentHandler] performWithDocument:^(UIManagedDocument *document) {
        self.document = document;         
    }];
} 

这在我的应用程序的任何其他地方都可以正常工作,但对于我的 tableView 中的委托方法来说,打开过程似乎不够快。

到目前为止我看过的链接:

http://omegadelta.net/2011/05/10/how-to-wait-for-ios-methods-with-completion-blocks-to-finish/

执行代码块代替@selector

关于 dispatch_queue_t 和 dispatch_sync 的调用

Grand Central Dispatch (GCD) 与 performSelector - 需要更好的解释

GCD 在主线程中执行任务

iOS - 如何在线程(使用 GCD)结束它的工作时收到通知

我试过:阻塞主线程直到我得到 NSNotification(在 CATManagedDocumentHandler 中设置)&阻塞主线程直到我得到一个块回调。

这些都不起作用。我的应用程序只是冻结。我想错了吗?如何让委托方法等到我的文档打开/准备好?或者我应该采取不同的方法吗?

谢谢

卡尔。

4

1 回答 1

0

好的,当您的应用程序第一次启动时,我建议检查 1. 您的数据库是否存在(如果不存在,则分配初始化它)和 2. 如果文档不存在(在磁盘上),是否已关闭或打开.

你可以这样做:

看起来您正在为您的数据库使用单例,因此当您的第一个视图控制器出现时,检查托管文档是否已被分配,因此在 ViewWillAppear 中:

if (!dataBase)
{
        NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        url = [url URLByAppendingPathComponent:@"Your DB Name"];
        self.dataBase=[[UIManagedDocument alloc]initWithFileUrl:url];
}

所以现在如果数据库(UIManagedDocument)已经被分配,它仍然不意味着实际的数据库文件已经在磁盘上创建。您必须按如下方式检查它(您可以在数据库的设置器或 ViewDidLoad 中执行此操作,但不要在另一个线程中执行此操作,因为它不起作用)

所以你在这里检查3个案例:不存在

if (![[NSFileManager defaultManager]fileExistsAtPath:[yourManagedDocumentFromSingleton.fileUrl path])
{
   [[NSFileManager defaultManager]fileExistsAtPath:[yourManagedDocumentFromSingleton saveToUrl:[[NSFileManager defaultManager]fileExistsAtPath:[yourManagedDocumentFromSingleton.fileUrl forSaveOperation:UIDocumentSaveForCreating completionHandler: 
^(BOOL success){ now you can use your uidocument and its managed object context}];
    }

如果文件确实存在但已关闭:

else if (yourManagedDocumentFromSingleton.documentState==UIDocumentStateClosed)
{
[yourManagedDocumentFromSingleton openWithCompletionHandler:
^(BOOL success) {use your document here}];
}

最后,如果文档已经打开,只需使用它:

else if (yourManagedDocumentFromSingleton.documentState=UIDocumentStateNormal)
{
//do whatever with the document
}

需要提到的一件重要事情是 UIDocument 不是线程安全的。所以它必须在创建它的同一个线程中使用和检查(这里大概是主线程)。否则它将无法正常工作。

我不知道您的视图控制器或单例的确切结构,但如果您按照这些步骤操作,它将起作用。

PS。还要确保一旦您的文档启动并运行并且您正在向其中添加或删除项目,请在每次操作后保存它,以便您的 NSFetchedResultsController 得到更新。CoreData 确实有自动保存功能,但我发现我必须手动保存才能正常工作。您可以使用(从以前的方法)保存:

forSaveOperation:UIDocumentSaveForOverwriting
于 2012-12-08T17:03:39.297 回答