В каких сценариях используется несколько UIWindow в iOS?

Ответ

Основные сценарии использования нескольких окон:

  1. Кастомные системные оверлеи

    • Всплывающие окна, тосты, кастомные алерты
    • Пример: баннеры поверх всего контента
  2. Поддержка внешних дисплеев

    // Создание окна для внешнего экрана
    if let externalScreen = UIScreen.screens.first(where: { $0 != .main }) {
       let externalWindow = UIWindow(frame: externalScreen.bounds)
       externalWindow.screen = externalScreen
       externalWindow.rootViewController = ExternalDisplayVC()
       externalWindow.isHidden = false
    }
  3. Экран блокировки/заставки

    • Отображение контента поверх пароля/Touch ID
  4. Picture-in-Picture (PiP) и плавающие окна

  5. Отладка и разработка

    • Окно для логов, FPS-метра, инструментов разработчика

Критически важные параметры:

let alertWindow = UIWindow(frame: UIScreen.main.bounds)

// Уровень окна определяет порядок наложения:
alertWindow.windowLevel = .alert + 1  // Выше стандартных алертов
alertWindow.windowLevel = .statusBar + 1  // Выше статус-бара

// Для основного окна:
UIApplication.shared.windows.first?.windowLevel = .normal

// Управление видимостью:
alertWindow.isHidden = false
alertWindow.makeKeyAndVisible()  // Делает окно ключевым

Рекомендации:

  • Всегда управляйте жизненным циклом дополнительных окон
  • Не создавайте окна без необходимости (потребление памяти)
  • Используйте windowLevel для контроля порядка отображения
  • Для кастомных алертов рассмотрите UIViewController с модальным презентом

Ответ 18+ 🔞

А, слушай, смотри, вот эта тема с несколькими окнами в iOS — это ж, блядь, целое искусство, а не просто хуйня какая-то! Многие думают, что одно окно — и всё, приехали. Ан нет, ёпта! Можно творить такое, что сам от себя офигеешь.

Основные сценарии, где это пиздец как полезно:

  1. Кастомные системные оверлеи Всплывашки свои, тосты, алерты, которые не как у всех. Вот, например, баннер, который должен быть поверх всего — даже поверх системного алерта или клавиатуры. Без своего окна — нихуя не выйдет, утонет.

  2. Поддержка внешних дисплеев Вот тут вообще магия начинается. Пользователь подключил телевизор или монитор — и ты можешь на него вывести свой контент, а на основном телефоне оставить управление. Красота же!

    // Ищешь внешний экран, который не основной
    if let externalScreen = UIScreen.screens.first(where: { $0 != .main }) {
        // БАЦ! Создаёшь для него отдельное окно
        let externalWindow = UIWindow(frame: externalScreen.bounds)
        externalWindow.screen = externalScreen // Вот это ключевое, блядь!
        externalWindow.rootViewController = ExternalDisplayVC()
        externalWindow.isHidden = false // И вуаля — понеслась!
    }
  3. Экран блокировки/заставки Хочешь показать какую-нибудь хуйню (пардон, важную информацию) прямо поверх экрана ввода пароля или перед Face ID? Пожалуйста — своё окно с уровнем повыше.

  4. Picture-in-Picture (PiP) и плавающие окна Ну, это понятно, видео в уголке плавает. Тоже часто своё окошко.

  5. Отладка и разработка Окошко с логами, которое висит поверх всего приложения, или FPS-метр. Удобно, ёпта, не надо в консоль постоянно смотреть.

А теперь, внимание, самое важное — параметры, без которых нихуя не получится:

let alertWindow = UIWindow(frame: UIScreen.main.bounds)

// Уровень окна — это, блядь, святое! Он решает, кто поверх кого будет.
alertWindow.windowLevel = .alert + 1  // Будет выше стандартных системных алертов
alertWindow.windowLevel = .statusBar + 1  // А это — выше статус-бара, вообще царь!

// У основного окна обычно уровень .normal
UIApplication.shared.windows.first?.windowLevel = .normal

// Видимость управляется просто:
alertWindow.isHidden = false
alertWindow.makeKeyAndVisible()  // Эта команда делает окно ключевым и показывает

И напоследок, жизненные советы, чтобы не обосраться:

  • Жизненный цикл — твой друг. Создал окно — не забудь его убить, когда оно не нужно. А то память жрать будет, как не в себя.
  • Не плоди сущности. Не создавай окна просто так, от скуки. Каждое новое окно — это ресурсы.
  • windowLevel — твоя власть. Хочешь, чтобы твой алерт был самым главным — подними ему уровень. Хочешь спрятать за чем-то — опусти.
  • Не усложняй. Для простых кастомных алертов иногда проще сделать модальный UIViewController, чем городить отдельное окно. Не надо из пушки по воробьям, ёпта.

Вот и вся наука. Главное — понять, зачем тебе это надо, и не накосячить с уровнями. А то получится, что твой важный баннер будет торчать из-под клавиатуры, как хитрая жопа.