0

私は非常に珍しい問題をデバッグしている最中であり、何がうまくいかないのかについて誰かが洞察を持っているのではないかと思っていました。

NIBのコントローラークラスでは、同じNIBからNSPanelを取得し、NSWindow(コードで手動で作成されたもの)でモーダルにアプリを表示します。

[[NSApplication sharedApplication] beginSheet: myPanel
                               modalForWindow: window
                                modalDelegate: self
                               didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
                                  contextInfo: nil];
[[NSApplication sharedApplication] runModalForWindow: myPanel];

ここで、そのシートの[完了]ボタンをクリックすると、コードを実行していくつかのボタンを無効にし、スレッドを起動してユーザー入力が有効であることを確認します(リモートサービスで検証する必要があります)。このスレッドは、私が作成した別のバリデーターオブジェクトから起動されます。

// controller calls:
[validator validateCreds: creds
           notify: @selector(validationComplete:)
           onObject: self];

// validator object
validateInfo: (NSDictionary *)parms
      notify: (SEL)notifySelector
    onObject: (id)notifyObject
{
 // build up data with parms and notify info
 [[NSThread detachNewThreadSelector: @selector(remotevalidate:)
            toTarget: self withObject: data];
}

次に、検証が終了すると、バリデーターはコントローラーオブジェクトに通知します。

[notifyObject performSelectorOnMainThread: notifySelector
              withObject: results waitUntilDone: NO];

そして、私のコントローラーオブジェクトは、バリデーターオブジェクトが呼び出すメソッドで、ダイアログを強制終了します。

- (void)validationComplete: (id)data
{
   [[NSApplication sharedApplication] stopModal];
   [createTwitterPanel orderOut: nil];
   [[NSApplication sharedApplication] endSheet: createTwitterPanel
                                      returnCode: NSOKButton];
}

- (void)sheetDidEnd:(NSWindow *)sheet
         returnCode:(int)returnCode
        contextInfo:(void  *)contextInfo
{
    m_returnCode = returnCode;
}

私の問題:パネルが閉じている/消えても、ダイアログを表示していたウィンドウに何らかのシステムイベントが送信されるまで、上部のNSApprunModalForWindow:は終了しません。ウィンドウに移動、サイズ変更、または何かをしようとしたり、アプリケーションから切り替えたりすると、メソッドが突然終了し、実行が続行されます。ただし、待機の量は役に立たないようです。

コントローラクラスで呼び出されているすべてのメソッドがすべてメインアプリスレッドで呼び出されていることを確認しました。

さらに興味深い手がかりは、ダイアログにWebViewとrunModalForWindow:NSTextFieldの2つのコントロールがあることです。ウィンドウをクリックして強制的に終了しても、2つのコントロール間のタブ操作は失敗したままです。これは二度と機能しません。それは私のイベントループがホークされているようなものです。

waitUntilDone代わりにメインスレッドに通知を投稿するためにvalidationCompleteを変更してみました。また、メソッドで試してみましたが、performSelectorOnMainThreadまったく効果がありませんでした。

何か案は?私が見てみるべきことは?

4

1 に答える 1

3

NSApplicationのドキュメントから:

stopModalまたはstopModalWithCodeの代わりにabortModalを使用する必要があります。モーダルイベントループを、そのイベントループからのコールアウト以外の場所から停止する必要がある場合。つまり、モーダルウィンドウ内のユーザーのアクションに応じてループを停止する場合は、stopModalを使用します。それ以外の場合は、abortModalを使用します。たとえば、Application Kitのメインスレッドとは異なるスレッドで実行する場合、またはデフォルトのNSRunLoopのNSModalPanelRunLoopModeモードに追加したNSTimerに応答する場合は、abortModalを使用します。

それで、今日私は何かを学びました。

于 2009-10-18T06:05:40.780 に答える