Nano Hash - криптовалюты, майнинг, программирование

Модальное приложение NSPanel / sheet / dialog + NSThread == зависает?

Я занимаюсь отладкой чрезвычайно необычной проблемы, и мне было интересно, может ли кто-нибудь понять, что может пойти не так:

В классе контроллера из 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, но безрезультатно.

Любые идеи? Вещи, на которые я должен попытаться посмотреть?


  • Это целевое приложение 10.5, работающее под управлением Xcode 3.2.1 на 10.6.1. 18.10.2009

Ответы:


1

Из документации NSApplication:

abortModal следует использовать вместо stopModal или stopModalWithCode: когда вам нужно остановить модальный цикл событий из любого места, кроме вызова из этого цикла событий. Другими словами, если вы хотите остановить цикл в ответ на действия пользователя в модальном окне, используйте stopModal; в противном случае используйте abortModal. Например, используйте abortModal при работе в потоке, отличном от основного потока Application Kit, или при ответе на NSTimer, который вы добавили в режим NSModalPanelRunLoopMode по умолчанию NSRunLoop.

Итак, я кое-что узнал сегодня.

18.10.2009
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..