Я занимаюсь отладкой чрезвычайно необычной проблемы, и мне было интересно, может ли кто-нибудь понять, что может пойти не так:
В классе контроллера из NIB я беру NSPanel из того же NIB, а затем показываю его модально в 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;
}
Моя проблема: хотя панель закрывается / исчезает, верхнее NSApp runModalForWindow:
не закрывается до тех пор, пока какое-либо системное событие не будет отправлено в окно, в котором отображалось диалоговое окно. Попытка переместить, изменить размер или сделать что-либо с окном или иным образом отключиться от приложения внезапно приводит к завершению метода и продолжению выполнения. В противном случае, похоже, никакое ожидание не поможет.
Я убедился, что все методы, вызываемые в классе контроллера, вызываются в основном потоке приложения.
Еще более интересная подсказка заключается в том, что в диалоговом окне есть два элемента управления, WebView и NSTextField: даже если я принудительно завершу runModalForWindow:
, щелкнув по окну, переключение клавиш TAB между двумя элементами управления останется неудачным - оно просто никогда не сработает снова. Как будто мой цикл событий завязан.
Я пробовал изменить validationComplete: чтобы вместо этого публиковать уведомление в основном потоке, и я также играл с waitUntilDone
в методе performSelectorOnMainThread
, но безрезультатно.
Любые идеи? Вещи, на которые я должен попытаться посмотреть?