Что такое UIWindow в iOS приложении
Что проверяют
Понимаете ли вы, откуда берётся картинка на экране и куда приходят касания. UIWindow это место стыковки приложения с системой, и кандидат, который знает только «окно это контейнер для вью», обычно не знает ни цепочки респондеров, ни того, почему со сценами окно создаётся не там, где написано в старых статьях.
Как отвечать
UIWindow это наследник UIView без собственного содержимого. Задач у него три: держать rootViewController с его иерархией, быть корнем цепочки респондеров и задавать область экрана, в которой всё это показывается.
Ключевые свойства: rootViewController, windowScene, windowLevel (обычный уровень, алерты, статус-бар), isKeyWindow. Метод makeKeyAndVisible делает две вещи: назначает окно ключевым, то есть получателем событий без координат, и снимает isHidden.
События идут так: система отдаёт касание окну, окно ищет вью через hitTest, дальше событие поднимается по цепочке респондеров и заканчивается на окне, а за ним на UIApplication.
В современных проектах окно принадлежит сцене, а не делегату приложения:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = RootViewController()
window.makeKeyAndVisible()
self.window = window
}Окон бывает несколько: своё на каждую сцену, отдельное поверх основного для оверлеев, ещё одно для внешнего дисплея.
Где спотыкаются
Рассказывают про поле window в делегате приложения и теряются, когда просят показать это место в проекте со сценами. Там окно живёт в делегате сцены и создаётся конструктором с windowScene, а не по границам экрана.
Считают ключевое окно и верхнее одним и тем же. Ключевое получает события без координат, а сверху может лежать другое окно; устаревший keyWindow у объекта приложения при нескольких сценах возвращает не то, что ожидают.
Не могут объяснить, зачем окно не одно, и кладут баннеры внутрь иерархии rootViewController. Отдельное окно со своим windowLevel не ломает иерархию контроллеров и переживает смену корневого экрана.