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 和一个 NSTextField:即使我runModalForWindow:通过单击窗口强制退出,两个控件之间的 TABbing 仍然搞砸了——它再也无法正常工作了。就像我的事件循环被吓坏了。

我尝试更改validationComplete: 改为向主线程发布通知,并且我也使用了waitUntilDoneonperformSelectorOnMainThread方法,但都没有效果。

有任何想法吗?我应该尝试看的东西?

4

1 回答 1

3

从 NSApplication 文档:

必须使用 abortModal 而不是 stopModal 或 stopModalWithCode:当您需要从该事件循环的标注以外的任何位置停止模式事件循环时。换句话说,如果您想停止循环以响应用户在模态窗口中的操作,请使用 stopModal;否则,使用 abortModal。例如,当在与 Application Kit 的主线程不同的线程中运行时,或者在响应您添加到默认 NSRunLoop 的 NSModalPanelRunLoopMode 模式的 NSTimer 时,使用 abortModal。

所以,我今天学到了一些东西。

于 2009-10-18T06:05:40.780 回答