Как получить текущий эквивалент ключевого окна для многооконного SceneDelegate Xcode 11?
Я конвертирую свое приложение iOS13 для iPadOS в SceneDelegate (многооконное).
Как я могу получить текущее окно UIWindow из текущего SceneDelegate?
Я знаю, что может получить доступ к текущей сцене, используя UIView.window
или же UIViewController.view.window
, но у меня есть не UI класс (AppDelegate), где мне нужно получить окно (keyWindow до iOS12), чтобы показать снэк-бар поверх всего.
обычно я делал [UIApplication sharedApplication].keyWindow
но сейчас, конечно, это не так.
7 ответов
Swift 5.x / iOS 13.x
Вдохновленный многими решениями, чтобы вернуть свое старое свойство окна (ища его внутри connectedScenes), я реализовал небольшое расширение:
extension UIApplication {
var currentWindow: UIWindow? {
connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
}
}
Использование:
if let window = UIApplication.shared.currentWindow {
// do whatever you want with window
}
Вам нужно просто перебрать все окна и найти ключевое окно вручную.
for (UIWindow *window in [UIApplication sharedApplication].windows) {
if (window.isKeyWindow) {
// you have the key window
break;
}
}
НЕ используйтеUISceneActivationStateForegroundActive
как чек. Это означает, что что-то другое, и люди вводят ошибки, используя логику для поиска первогоUISceneActivationStateForegroundActive
оконная сцена.
Похоже, вы, вероятно, хотите перенести эту логику в свой SceneDelegate.
Теперь SceneDelegate знает, связано ли окно со сценой, поэтому может иметь смысл прослушивать каждую подключенную сцену независимо от события, которое ведет закусочную, и отображать его в своем окне. Это приведет к тому, что в каждом видимом окне будет отображаться закусочная (1 или более).
Вы можете попробовать:
if let window = UIApplication.shared.windows.first(where: { (window) -> Bool in window.isKeyWindow}) {
//your code
}
Надеюсь это поможет!
ДляSwiftUI
, Протестировано в iOS 16+
extension UIApplication {
var currentWindow: UIWindow? {
connectedScenes
.compactMap { $0 as? UIWindowScene }
.first?
.windows
.first
}
}
Это использование.
guard let anchor = UIApplication.shared.currentWindow else {
fatalError("Window did not found in Hierarchy")
}
Теперь у вас есть более одного окна, по одному для каждой сцены. Во-первых, вы должны ответить, какой из них вам нужен в момент использования.
Возможно, вы хотите получить окно текущей активной сцены, тогда вы можете использовать это:
UIWindow* window = nil;
if (@available(iOS 13.0, *))
{
for (UIWindowScene* wScene in [UIApplication sharedApplication].connectedScenes)
{
if (wScene.activationState == UISceneActivationStateForegroundActive)
{
window = wScene.windows.firstObject;
break;
}
}
}
Я еще не пробовал это, но вы должны быть в состоянии получить все окна с [UIApplication sharedApplication].windows
и затем выберите, хотите ли вы показать снэк-бар на всех окнах или одном окне.