2015-02-12 3 views
2

У меня есть ситуация, когда файл документа полагается на ссылку на другой внешний файл мультимедиа. Когда документ открывается, я проверяю, доступен ли ссылочный мультимедийный файл, а если нет, то пользователю предлагается найти его.Представление NSOpenPanel как лист синхронно

Поскольку имеет смысл показать NSOpenPanel как лист в приложении на основе документов, я хотел бы это сделать, но очень важно, чтобы текущий поток был заблокирован, поэтому последующий код не может быть вызван до тех пор, пока новый носитель файл выбран.

Я не могу найти способ представить этот NSOpenPanel в виде листа в окне документа, блокируя текущий поток. Только [NSOpenPanel runModal] делает то, что мне нужно, но это показывает как обычный диалог, а не лист.

Кажется, это должно быть возможно как-то ...

ответ

4

Предупреждение: Я предполагаю, что вы используете песочницу так 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 на вашем потоке, то надежное решение должно быть в твоем понимании.

Третье:

Да, я сказал только два, третий вариант даже не пытаются.

НТН

+0

Я полностью понимаю глубину вашего ответа, но поскольку это, надеюсь, редкое событие, я думаю, что я буду жить с несоответствием пользовательского интерфейса и выбрать вариант 3! – martinjbaker

0

есть атрибут на NSProgressIndicator, который говорит, погода или нет неопределенна. для достижения прогресса вы должны установить это значение NO

Смежные вопросы