Предупреждение: Я предполагаю, что вы используете песочницу так NSOpenPanel
& NSSavePanel
основаны на вуду - их поведение, как правило, зависит от точки выпуска ОС, фаза луны, есть ли в доме какой-нибудь голубой сыр и т. д., и заставить их вести себя нормально, может потребовать много терпения. (См. this question for one person's recent pain.) Да, я шучу - немного - но вы были предупреждены.
Еще здесь?
Известно, что код, похожий на оба из нижеперечисленных, работает в определенный момент времени, в течение полной луны и простого количества секунд за полночь.
Весь код просто набрал в ответ, ожидайте опечатки.
Первое:
+ (NSInteger) myRunModal:(NSOpenPanel *)myPanel
asSheetForWindow:(NSWindow *)myWindow
{
[myPanel beginSheetModalForWindow:myWindow
completionHandler:^(NSInteger result)
{
[NSApp stopModalWithCode:result];
}
];
return [NSApp runModalForWindow:myWindow];
}
Здесь после вызова beginSheetModalForWindow:
ваш поток входит в модальный цикл только обработку событий для окна. Когда обработчик завершения получает вызов, он исполняет его, завершает этот модальный цикл и возвращается результат.
Независимо от того, что вы делаете, НЕ ДЕЛАЙТЕ, чтобы добавить это как категорию в классы NSOpen/SavePanel. Это приводит к безумию. Помните, что они вуду, не путайте их с ними.
Второе:
Используйте семафор, с одной стороны, это кажется очевидным, с другими тупиковым сразу приходит на ум ...
+ (void) myRunModal:(NSOpenPanel *)myPanel
asSheetForWindow:(NSWindow *)myWindow
completionHandler:(void (^)(NSInteger))myHandler
{
// Use a semaphore to block thread till sheet is done
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[myPanel beginSheetModalForWindow:myWindow
completionHandler:^(NSInteger result)
{
myHandler(result);
// Unblock caller
dispatch_semaphore_signal(sema);
}
];
// Block until sheet completes
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
Здесь ваш поток ожидает семафор сигнал , Если система хочет выполнить обработчик в том же потоке, вы зашли в тупик. Попробует? Может быть.
Однако, если вы можете организовать свой код таким образом, что код, который нужно вызвать NSOpenPanel
работает на потоке, а затем организовать для beginSheetModalForWindow:
для запуска на главном потоке с dispatch_semaphore_wait
на вашем потоке, то надежное решение должно быть в твоем понимании.
Третье:
Да, я сказал только два, третий вариант даже не пытаются.
НТН
Я полностью понимаю глубину вашего ответа, но поскольку это, надеюсь, редкое событие, я думаю, что я буду жить с несоответствием пользовательского интерфейса и выбрать вариант 3! – martinjbaker