Ответ
Основной метод — viewWillTransition(to:with:). Он предпочтительнее уведомлений, так как работает универсально на всех устройствах (включая iPad с многозадачностью).
Использование viewWillTransition(to:with:):
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// size — новые размеры view контроллера
let isLandscape = size.width > size.height
// coordinator позволяет встроить свою анимацию в системную
coordinator.animate(alongsideTransition: { [weak self] _ in
// Анимируем изменения layout при повороте
self?.updateLayoutForOrientation(isLandscape: isLandscape)
}) { [weak self] _ in
// Действия после завершения анимации поворота
self?.logOrientationChange()
}
}
private func updateLayoutForOrientation(isLandscape: Bool) {
// Обновляем constraints или frames
someConstraint.constant = isLandscape ? 100 : 50
view.layoutIfNeeded() // Применяем изменения с анимацией
}
Альтернатива — уведомление (менее предпочтительно):
// Подписка (например, в viewDidLoad)
NotificationCenter.default.addObserver(
self,
selector: #selector(orientationDidChange),
name: UIDevice.orientationDidChangeNotification,
object: nil
)
@objc private func orientationDidChange() {
let orientation = UIDevice.current.orientation
// Обработка...
}
Почему viewWillTransition лучше?
- Универсальность: Срабатывает при любом изменении размера view (поворот, split view на iPad, изменение window size).
- Координация анимаций:
UIViewControllerTransitionCoordinatorпозволяет синхронизировать ваши анимации с системными. - Контроль: Вы получаете точные новые размеры (CGSize), а не абстрактную "ориентацию устройства".
Дополнительно: Для реагирования на изменение размеров, вызванное Auto Layout, также можно переопределить viewWillLayoutSubviews() или traitCollectionDidChange(_:) (для изменений trait collections, таких как size class).
Ответ 18+ 🔞
А, слушай, вот этот момент с поворотом экрана — это вообще отдельная песня, блядь. Все эти новички лезут в NotificationCenter, подписываются на ориентацию устройства, а потом на iPad у них всё ебётся, потому что split view или slide over. Пиздец, а не подход.
Так вот, есть у нас метод viewWillTransition(to:with:). Вот это, блядь, наш бро, наш чёрный властелин. Он работает везде, сука, как швейцарский нож: и на айфоне при повороте, и на айпаде, когда ты там окно резиновое таскаешь. Универсальный солдат, ёпта.
Как его, сука, применять:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// size — это вот новые габариты твоего вью, уже по факту, блядь
let isLandscape = size.width > size.height // Альбомная? Да по ширине смотри!
// А coordinator — это вообще магия, он позволяет твою анимацию в системную впихнуть
coordinator.animate(alongsideTransition: { [weak self] _ in
// Тут всё, что должно анимироваться плавненько
self?.updateLayoutForOrientation(isLandscape: isLandscape)
}) { [weak self] _ in
// А это уже после того, как всё завертелось
self?.logOrientationChange() // Ну, логируй там, если охота
}
}
private func updateLayoutForOrientation(isLandscape: Bool) {
// Ну тут уже твоё творчество: констрейнты двигай, фреймы меняй
someConstraint.constant = isLandscape ? 100 : 50
view.layoutIfNeeded() // Без этого — нихуя не анимируется, запомни
}
А есть же ещё старый способ, через уведомления (но он так себе, честно):
// Вешаем слушателя (например, в viewDidLoad)
NotificationCenter.default.addObserver(
self,
selector: #selector(orientationDidChange),
name: UIDevice.orientationDidChangeNotification,
object: nil
)
@objc private func orientationDidChange() {
let orientation = UIDevice.current.orientation
// И тут начинается геморрой с обработкой .faceUp, .faceDown...
}
Так почему же viewWillTransition — это охуенно, а уведомления — говно?
- Универсальность, блядь! Тебе приходит просто новый размер вью. Похуй, как он изменился: поворот, многозадачность на айпаде, окно поменяли — всё одно.
- Координатор анимаций! Ты можешь свою анимацию встроить в системную, и будет красиво, а не дёргано. Без него — волнение ебать, всё моргает.
- Контроль полный! Тебе дают конкретные цифры —
CGSize. Не надо гадать, что там с устройством, может оно вообще лежит экраном вверх.
Ну и на закуску: Если тебе надо просто на изменение размеров от Auto Layout среагировать — есть viewWillLayoutSubviews(). А если тебе важны size classes (компактный, регулярный) — то traitCollectionDidChange(_:). Но для поворота — первый метод, царь и бог, запомни это, чтобы не выдумывать хуйню.