2016-09-23 2 views
1

В какао (Objective-C), как вы можете программно одновременно демининизировать группу экземпляров NSWindow без с использованием фоновой темы?Одновременно деминерализовать массив NSWindows программно?

Если вы вызываете «deminiaturize:» в экземпляре NSWindow, он блокирует основной поток в течение всего процесса демининатизации (около 0,3 секунды). Если вы укажете массив окон для деминиратизации, они будут делать это по одному, кумулятивно занимая довольно много времени, все время блокируя основной поток. Желаемый аффект может быть достигнут с использованием фонового потока, но это (правильно) вызывает ошибки журнала консоли.

Возможность безопасной деминерализации группы из 5+ окон за 0.3 секунды или менее была бы идеальной. Есть ли способ удалить анимацию из демининатизации, чтобы ускорить процесс? Есть ли другой способ восстановить окна на экран без вызова «deminiaturize:»?

+0

Док выполняет деминализацию. Эффект масштабирования выполняется быстрее. Нажмите кнопку сдвига для замедленного движения. – Willeke

+0

'close' не будет выпускать окно, если' releaseWhenClosed' является ложным. – Willeke

ответ

2

При использовании комбинации setReleasedWhenClosed:, close и makeKeyAndOrderFront:, можно эффективно deminiaturize массива NSWindows без какой-либо анимации (то есть мгновенно) - и фактически не deallocating объектов.

Objective-C:

void deminiaturizeWindowsWithoutAnimation(NSArray<NSWindow *> *windows) { 
    for (NSWindow * window in windows) { 
     if ([window isMiniaturized]) { 
      BOOL old_isReleasedWhenClosed = [window isReleasedWhenClosed]; 
      [window setReleasedWhenClosed:false]; 
      [window close]; 
      [window makeKeyAndOrderFront: nil]; 
      [window setReleasedWhenClosed:old_isReleasedWhenClosed]; 
     } 
    } 
} 

Свифта:

func deminiaturizeWithoutAnimation(windows: [NSWindow]) { 
    for window in windows { 
     guard window.isMiniaturized else { continue } 
     let old_isReleasedWhenClosed = window.isReleasedWhenClosed 
     window.isReleasedWhenClosed = false 
     window.close() 
     window.makeKeyAndOrderFront(nil) 
     window.isReleasedWhenClosed = old_isReleasedWhenClosed 
    } 
} 

Эти функции могут быть вызваны из главного потока. Протестировано на macOS Sierra.

Если вы хотите, вы можете заменить makeKeyAndOrderFront: на orderFront: или orderBack:, чтобы избежать изменения ключевого окна. (Хотя поведение makeKeyAndOrderFront повторяет поведение deminiaturize:, что приводит к тому, что окно становится ключевым окном.)

+1

Это отличный ответ. Мне пришлось сохранять и восстанавливать оконный контроллер и делегат окна, а также перехватывать NSWindowWillCloseNotification для некоторых типов окон (которые по существу созданы/сохранены только раскадрой). Кроме того, новые окна с вкладками в macOS 10.12 ungroup с использованием этого решения ... но в целом он делает то, что мне нужно, спасибо за это! –

+0

Отличные очки. Копаясь в том, как «deminiaturize:» работает, привело к кучке частных внутренних компонентов NSWindow и частной инфраструктуры CoreDock. Гораздо проще использовать этот трюк, чтобы избавиться от окна в доке, а затем повторно отобразить его, чем попробовать метод swizzling внутренних селекторов NSWindows или использовать эту приватную инфраструктуру (которая также не будет совместима с Mac App Store и вероятно, перерыв в будущей версии ОС - этот метод значительно безопаснее). – breakingobstacles

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