У меня есть приложение, состоящее из следующего единственного файла .m:

#import <Cocoa/Cocoa.h>

int main(int argc, char* argv[]) {
  [[[NSThread alloc] initWithBlock: ^{
    sleep(2);
    dispatch_async(dispatch_get_main_queue(), ^{ 
      NSLog(@"Stop");
      [[NSApplication sharedApplication] stop:nil];
    });
  }] start];
  [[NSApplication sharedApplication] run];
  NSLog(@"Run finished");
  return 0;
}

Согласно документации разработчика, stop должен остановить основной цикл (run), но это не так (по крайней мере, не в OS X 10.12 и 10.13). Также есть terminate, но он тоже выходит из программы скоро. Я также пробовал установить NSApplicationDelegate, реализующий applicationShouldTerminate, но он никогда не вызывается.

Как я могу убедиться, что основной цикл выполнения (чисто) завершен?

Примечание. Основной цикл общего приложения необходим, поскольку пользовательский интерфейс выполняется где-то еще. Более конкретно, это создает проблемы в библиотеке пользовательского интерфейса Go WDE, которая использует Какао для предоставления окно в приложение Go.

2
Remko 31 Дек 2017 в 12:08

2 ответа

Лучший ответ

В документации для -stop: говорится:

[C] использование этого метода из таймера или подпрограммы наблюдателя цикла выполнения не остановит цикл выполнения, потому что они не приводят к отправке объекта NSEvent.

Блок, отправленный в основную очередь, аналогичен тому, что он не публикует событие. Вы можете попробовать опубликовать событие NSEventTypeApplicationDefined после вызова -stop:.

2
Ken Thomases 2 Янв 2018 в 16:46

После дальнейшего исследования выяснилось, что запрос цикла пользовательского интерфейса stop обрабатывается только после события UI (а не сразу после события основного цикла). Итак, он работает в ответ на событие пользовательского интерфейса, но не в потоке, как в моем примере.

Запуск события пользовательского интерфейса после запроса stop (например, для меня работает программное изменение размера) приводит к завершению цикла.

0
Remko 2 Янв 2018 в 16:47