← Назад к вопросам

В каком методе можно отследить поворот экрана?

1.6 Junior🔥 242 комментариев
#UIKit и верстка

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Методы отслеживания поворота экрана в iOS

В iOS разработке существует несколько основных подходов для отслеживания изменения ориентации устройства. Вот ключевые методы и best practices:

1. ViewController Lifecycle Methods

Наиболее распространенный способ — использование методов жизненного цикла UIViewController:

class ViewController: UIViewController {
    
    // Вызывается перед изменением размеров вью
    override func viewWillTransition(to size: CGSize, 
                                     with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        
        coordinator.animate(alongsideTransition: { context in
            // Анимация во время поворота
            if UIDevice.current.orientation.isLandscape {
                print("Устройство переходит в альбомную ориентацию")
            } else {
                print("Устройство переходит в портретную ориентацию")
            }
        }, completion: { context in
            // Действия после завершения поворота
            print("Поворот завершен")
        })
    }
    
    // Вызывается при изменении размеров вью
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        
        if traitCollection.verticalSizeClass == .compact {
            // Компактная высота (обычно альбомный режим)
        } else {
            // Обычная высота (обычно портретный режим)
        }
    }
}

2. Trait Collection Changes

Использование UITraitCollection для отслеживания изменений характеристик устройства:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    if traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass ||
       traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass {
        
        print("Изменение size class:")
        print("Горизонтальный: \(traitCollection.horizontalSizeClass == .compact ? "compact" : "regular")")
        print("Вертикальный: \(traitCollection.verticalSizeClass == .compact ? "compact" : "regular")")
    }
}

3. Notification Center

Подписка на системные уведомления об изменении ориентации:

class OrientationObserver {
    
    init() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(orientationDidChange),
            name: UIDevice.orientationDidChangeNotification,
            object: nil
        )
        
        // Включаем генерацию событий поворота
        UIDevice.current.beginGeneratingDeviceOrientationNotifications()
    }
    
    @objc func orientationDidChange() {
        let orientation = UIDevice.current.orientation
        
        switch orientation {
        case .portrait:
            print("Портретная ориентация")
        case .portraitUpsideDown:
            print("Портретная ориентация (перевернутая)")
        case .landscapeLeft:
            print("Альбомная ориентация (влево)")
        case .landscapeRight:
            print("Альбомная ориентация (вправо)")
        case .faceUp, .faceDown:
            print("Устройство лежит лицом вверх/вниз")
        default:
            print("Неизвестная ориентация")
        }
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
        UIDevice.current.endGeneratingDeviceOrientationNotifications()
    }
}

4. Современный подход (iOS 16+)

В iOS 16 появились новые API для работы с ориентацией:

// В SceneDelegate для поддержки различных ориентаций
func application(_ application: UIApplication,
                 supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return [.portrait, .landscape]
}

// Использование responsive layouts с Size Classes
func configureLayoutForCurrentOrientation() {
    let isLandscape = UIDevice.current.orientation.isLandscape
    let isPortrait = UIDevice.current.orientation.isPortrait
    
    if isLandscape {
        applyLandscapeLayout()
    } else if isPortrait {
        applyPortraitLayout()
    }
}

5. Key Considerations

  • Разница между device orientation и interface orientation: UIDeviceOrientation относится к физическому положению устройства, а UIInterfaceOrientation — к ориентации интерфейса.
  • Поддержка нескольких ориентаций: настройка в Info.plist или через supportedInterfaceOrientations
  • Автоматический layout: использование Auto Layout с constraints, которые адаптируются к изменениям
  • Size Classes: предпочтительный способ создания адаптивных интерфейсов
  • Безопасные области: учет safeAreaInsets при изменении ориентации

Best Practices

  • Используйте Auto Layout для автоматической адаптации интерфейса
  • Тестируйте на реальных устройствах, так как симулятор может не полностью воспроизводить поведение
  • Учитывайте разные размеры экрана (iPhone, iPad, Split View)
  • Избегайте жестких размеров в пользу адаптивных решений
  • Для сложных переходов используйте UIViewControllerTransitionCoordinator

Наиболее правильным подходом считается использование комбинации Auto Layout, Size Classes и метода viewWillTransition(to:with:), что обеспечивает наиболее гибкую и предсказуемую адаптацию интерфейса к изменениям ориентации устройства.

В каком методе можно отследить поворот экрана? | PrepBro