2

モーダルセッションとして表示したいメインウィンドウとサブウィンドウを備えたアプリケーションを構築しています。だから私はウィンドウコントローラー内でこのコードを使用しています:

self.session = [[NSApplication sharedApplication] beginModalSessionForWindow: self.window];
[[NSApplication sharedApplication] runModalSession: self.session];

ただし、このコードをどこに置いたか(windowDidLoad、メインウィンドウからのpost-windowDidLoad呼び出し、またはウィンドウコントローラーのinit関数)に関係なく、取得するのはモードレスサブウィンドウです。サブウィンドウはメインウィンドウの上に表示されますが、メインウィンドウは引き続き入力イベントに応答します。

私は何が間違っているのですか?

4

1 に答える 1

3

nvm-いくつかの例を読んで私の答えを見つけました。(繰り返しになりますが、Stackに投稿する前の何時間もの調査では答えが得られず、投稿直後に洞察に出くわしました。)

後世のために、ここに答えがあります:beginModalSessionForWindowはrunModalForWindowのようには機能しません。

runModalを使用すると、そのコードをどこでも実行でき、Cocoaはモーダルウィンドウを除くすべての処理を即座に停止します。(残念ながら、これにはバックグラウンド処理のために非UIイベントに関連付けられたタイマーが含まれます。)runModalを実行するコードはブロックされ、モーダルウィンドウが閉じられた後にのみ再開されます。システムはウィンドウのモダリティを適用します。

beginModalSessionForWindowの動作は大きく異なります。どこで実行しても、コードはモーダルウィンドウを起動し、実行を続けます。一般的なユースケース(Appleの例で示されているように)では、ループの前にbeginModalを呼び出してから、セッションのステータスをポーリングするようにループを条件付けると、ループは他の必要な処理を実行できます。また、ループ中は、通常のUIイベントもブロックします。これは、長時間実行されるループを実行する場合のIBActionと同じです。

重要なのは、beginModalSessionは実際にはウィンドウのモダリティを強制しないということです。むしろ、コードは、長時間実行されるループを実行することにより、ウィンドウのモダリティを強制します。ループを使用せず、代わりに「モーダル」セッションを実行して通常のイベントループを再開する場合は、他のウィンドウがUIイベントを含むすべてのイベント処理を取得します。「モーダル」ウィンドウはモードレスになります。

「beginModalSessionForWindow」は実際にはbeginModelessSessionForWindowと呼ばれるべきであると主張します。これは、それが行うことであり、モードレスウィンドウを作成して戻ります。

于 2012-09-27T18:50:43.393 に答える