3

私の文書ベースのアプリケーションでは、独自の openPanel を表示できるように、NSDocumentcontroller のサブクラスでメソッド openDocument: をオーバーライドしました。選択した 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

コメントを回答に変換する:

メイン スレッドで runModel を実行します。

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

runModel は AppKit フレームワークの一部であり、本質的に UI グラフィックをトリガーしているため、メイン スレッドで呼び出す必要があると思います。AppKit フレームワークまたはグラフィックスを操作するメソッドへのすべての呼び出しは、メイン スレッド上で行う必要があると思います。

于 2012-10-02T17:38:29.640 に答える