3

在我的基于文档的应用程序中,我在我的 NSDocumentcontroller 子类中重写了方法 openDocument:,以便我可以显示我自己的 openPanel。我将选择的 URL 传递给方法 openDocumentWithContentsOfURL:display:completionHandler:。我使用此代码进行通话:

[self openDocumentWithContentsOfURL:[chosenFiles objectAtIndex:i] display:YES completionHandler:^(NSDocument *document, BOOL documentWasAlreadyOpen, NSError *error) {

    if (document == nil)
    {
        NSAlert* alert = [NSAlert alertWithError:error];
        [alert runModal];
    }

}];

因此,如果 nil 作为对文档的引用返回,我想显示传递的错误。问题是,在我按下打开面板中的“打开”按钮后,程序只是“冻结”了。然后我需要使用 Xcode 中的“停止”按钮手动停止程序。但是,没有出现旋转的沙滩球。如果我注释“[alert runModal]”行,程序不会再冻结,但当然不会显示警报。

现在奇怪的是:代码有时有效。如果我从 Xcode 切换到我的浏览器并返回并再次运行该程序,它有时会完美运行并显示错误。一段时间后,它再次停止工作。这是不可预测的,但大多数时候它不起作用。

这一切对我来说听起来像是一种竞争条件。肯定跟区块有关系吧?但是我做错了什么?

4

1 回答 1

1

将我的评论转换为答案:

在主线程上运行模型。

[alert performSelectorOnMainThread:@selector(runModal) withObject:nil waitUntilDone:NO]; 

我认为 runModel 需要在主线程上调用,因为它是 AppKit 框架的一部分,它本质上是触发 UI 图形。我相信对 AppKit 框架或任何操作图形的方法的所有调用都需要在主线程上。

于 2012-10-02T17:38:29.640 回答