Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Добавление нескольких UIWindow на iPad
Для добавления двух или более UIWindow на iPad используются те же принципы, что и на iPhone, но с учетом особенностей multitasking и большей площади экрана. Современный подход (iOS 13+) использует UIWindowScene, а для более старых версий iOS — прямое создание окон через UIWindow(frame:).
Ключевые концепции
UIWindowScene(iOS 13+): Каждое окно принадлежит определенной сцене, которая представляет отдельный экземпляр приложения (особенно важно для iPad multitasking).- Иерархия окон: Основное окно (
keyWindow) и дополнительные окна, которые могут отображаться поверх. - Управление видимостью: Окно становится видимым после установки
isHidden = falseи вызоваmakeKeyAndVisible().
Практическая реализация
Рассмотрим два основных сценария: создание окон в SceneDelegate (iOS 13+) и в AppDelegate (универсальный подход).
Способ 1: Использование SceneDelegate (iOS 13+)
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var mainWindow: UIWindow?
var secondaryWindow: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
// Главное окно
mainWindow = UIWindow(windowScene: windowScene)
let mainViewController = MainViewController()
mainWindow?.rootViewController = mainViewController
mainWindow?.windowLevel = .normal
mainWindow?.makeKeyAndVisible()
// Второе окно (в той же сцене)
secondaryWindow = UIWindow(windowScene: windowScene)
let secondaryViewController = SecondaryViewController()
secondaryWindow?.rootViewController = secondaryViewController
// Настройка положения и размера второго окна
secondaryWindow?.frame = CGRect(x: 50, y: 200, width: 300, height: 400)
secondaryWindow?.windowLevel = .normal + 1 // Чуть выше главного
secondaryWindow?.isHidden = false
secondaryWindow?.backgroundColor = .systemBackground
// Для iPad: учитываем безопасные зоны
secondaryWindow?.insetsLayoutMarginsFromSafeArea = true
}
func toggleSecondaryWindow() {
guard let secondaryWindow = secondaryWindow else { return }
secondaryWindow.isHidden.toggle()
}
}
Способ 2: Универсальный подход (работает на всех версиях iOS)
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var overlayWindow: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Основное окно приложения
window = UIWindow(frame: UIScreen.main.bounds)
let rootVC = ViewController()
window?.rootViewController = rootVC
window?.makeKeyAndVisible()
// Создаем второе окно
createOverlayWindow()
return true
}
private func createOverlayWindow() {
// Используем отдельный UIWindow для overlay
overlayWindow = UIWindow(frame: CGRect(x: 100, y: 100, width: 300, height: 400))
let overlayVC = OverlayViewController()
overlayWindow?.rootViewController = overlayVC
overlayWindow?.backgroundColor = .white
// Настройка уровня окна
overlayWindow?.windowLevel = UIWindow.Level.alert + 1 // Очень высокий уровень
// Границы и тень для визуального отделения
overlayWindow?.layer.cornerRadius = 12
overlayWindow?.layer.shadowOpacity = 0.3
// Делаем окно видимым
overlayWindow?.isHidden = false
// Добавляем возможность перемещения (опционально)
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
overlayWindow?.addGestureRecognizer(panGesture)
}
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
guard let window = overlayWindow else { return }
let translation = gesture.translation(in: window)
window.center = CGPoint(x: window.center.x + translation.x,
y: window.center.y + translation.y)
gesture.setTranslation(.zero, in: window)
}
// Для iPad Multitasking (iOS 13+)
@available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
}
Особенности для iPad
-
Multitasking и Multiple Windows:
- На iPad приложение может иметь несколько сцен одновременно
- Каждая сцена может содержать свои окна
- Используйте
UIWindowSceneдля правильной интеграции
-
Безопасные области (Safe Area):
// При создании окон на iPad учитывайте safe area insets secondaryWindow?.frame = UIEdgeInsetsInsetRect(UIScreen.main.bounds, windowScene.windows.first?.safeAreaInsets ?? .zero) -
Уровни окон (Window Levels):
.normal(0.0) - стандартный уровень.alert(2000.0) - для алертов.statusBar(1000.0) - поверх статус бара- Кастомные уровни: создавайте свои значения для точного контроля
Практические рекомендации
- Управление памятью: Всегда проверяйте, что дополнительное окно не создает retain cycles
- Обработка событий: События касаний автоматически отправляются в верхнее видимое окно
- Адаптивность: На iPad учитывайте изменение ориентации и размеров окон
- Архитектура: Используйте паттерны делегатов или уведомлений для связи между окнами
// Пример обновления frame при повороте
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { _ in
// Обновляем размер и положение дополнительного окна
self.secondaryWindow?.frame = self.calculatedFrameForCurrentOrientation()
})
}
Типичные use cases
- Плавающие элементы интерфейса (чаты, плееры)
- Вспомогательные панели и палитры в creative-приложениях
- Модальные окна с особым поведением
- Кастомные уведомления и toast-сообщения
- Инструментальные панели в редакторах
Реализация нескольких окон на iPad требует внимания к архитектуре, управлению памятью и корректной обработке multitasking, но открывает возможности для создания продвинутых пользовательских интерфейсов с гибким управлением областями содержимого.