Реализация Split View / Slide Over для iPad-приложения
iPadOS Multitasking — Split View (два приложения рядом), Slide Over (приложение в плавающем окне), Stage Manager (iOS 16+, окна свободного размера) — всё это работает только если приложение правильно поддерживает гибкие размеры окна. Приложение, задеплоенное на iPad без поддержки Multitasking, отображается с тёмными полосами в компактном режиме и не попадает в список доступных для Split View — это сразу видно как недоработка.
Что нужно для базовой поддержки
Включить Multitasking в Info.plist. Для полной поддержки Split View и Slide Over — убрать UIRequiresFullScreen = YES. Если этот ключ установлен в true, приложение принудительно занимает весь экран и недоступно для Split View.
SceneDelegate и поддержка Multiple Windows — необходима для Stage Manager:
// Info.plist
// UIApplicationSceneManifest → UISceneConfigurations → UIWindowSceneSessionRoleApplication
// Там же: UIApplicationSupportsMultipleScenes = true
AutoLayout без захардкоженных размеров. Это 90% работы. Каждый frame, constant и multiplier рассчитывается от view.bounds — не от магических 768 или 1024.
Размерные классы: traitCollection вместо hardcode
iPad в Split View меняет horizontalSizeClass с .regular на .compact при узком окне. Код, завязанный на UIDevice.current.userInterfaceIdiom == .pad вместо size class, сломается:
// Плохо — завязка на устройство
if UIDevice.current.userInterfaceIdiom == .pad {
showSidebar()
}
// Правильно — завязка на size class
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.horizontalSizeClass == .regular {
showSidebar()
} else {
hideSidebar()
}
}
В SwiftUI — @Environment(\.horizontalSizeClass):
struct ContentView: View {
@Environment(\.horizontalSizeClass) var sizeClass
var body: some View {
if sizeClass == .regular {
NavigationSplitView {
SidebarView()
} detail: {
DetailView()
}
} else {
NavigationStack {
MainView()
}
}
}
}
NavigationSplitView — нативный компонент для iPad master-detail. Автоматически адаптируется под разные size class, поддерживает три-колоночный layout (sidebar, content, detail) без ручного управления.
UISplitViewController для UIKit
Для UIKit-приложений UISplitViewController — правильный выбор. Важные свойства:
let split = UISplitViewController(style: .doubleColumn)
split.preferredDisplayMode = .oneBesideSecondary
split.preferredSplitBehavior = .tile
split.presentsWithGesture = true // свайп для скрытия sidebar
// Минимальная ширина primary колонки
split.minimumPrimaryColumnWidth = 280
split.maximumPrimaryColumnWidth = 400
split.preferredPrimaryColumnWidth = 320
style: .tripleColumn для трёхколоночного layout (почта, сообщения). presentsWithGesture = true позволяет скрывать/показывать sidebar свайпом — ожидаемое поведение на iPad.
Адаптация при коллапсе: когда Split View уходит в компактный режим (Slide Over, узкий Split), контроллеры «сворачиваются» в стек. Переопределяем логику через делегат:
func splitViewController(
_ svc: UISplitViewController,
topColumnForCollapsingToProposedTopColumn proposedTopColumn: UISplitViewController.Column
) -> UISplitViewController.Column {
// Показывать sidebar вместо detail при collapse, если detail пуст
if detailViewController.isEmpty {
return .primary
}
return proposedTopColumn
}
Drag & Drop между колонками
В Split View пользователи ожидают Drag & Drop — особенно в продуктивных приложениях. UIDropInteraction и UIDragInteraction добавляются к View:
let dropInteraction = UIDropInteraction(delegate: self)
targetView.addInteraction(dropInteraction)
func dropInteraction(_ interaction: UIDropInteraction,
performDrop session: UIDropSession) {
session.loadObjects(ofClass: NSString.self) { items in
// Обрабатываем дроп
}
}
Для SwiftUI — .onDrop(of:delegate:) и .draggable().
Keyboard и Pointer поддержка
iPad с Magic Keyboard — это трекпад и клавиатура. Без UIPointerInteraction (hover эффекты) и keyboard shortcuts приложение выглядит непроработанным на iPad Pro.
// Keyboard shortcut
let command = UIKeyCommand(input: "N", modifierFlags: .command,
action: #selector(newItem),
discoverabilityTitle: "Новый элемент")
addKeyCommand(command)
UIMenuBuilder для добавления пунктов в системное меню (Edit, View), что важно при работе с Magic Keyboard.
Ориентиры по срокам
| Задача | Срок |
|---|---|
| Базовая Split View поддержка (UISplitViewController) | 1–2 дня |
| Полная адаптация с size class, Drag & Drop | 3–4 дня |
| + Stage Manager + Keyboard shortcuts | +1 день |
| SwiftUI NavigationSplitView с нуля | 2–3 дня |







