Как определить размер экрана iOS устройства в Swift?
Современный способ получения размера экрана в Swift
Основная проблема, с которой вы столкнулись — это использование устаревших API и непонимание контекста, в котором нужен размер экрана. Давайте разберем правильные подходы.
1. Для получения физического размера экрана устройства (в точках):
import UIKit
let screenBounds = UIScreen.main.bounds
print("Ширина: \(screenBounds.width), Высота: \(screenBounds.height)")
UIScreen.main.bounds возвращает размер экрана в точках (points), а не в пикселях. Это важно, так как на разных устройствах разная плотность пикселей (например, @2x на iPhone 8, @3x на iPhone 12 Pro). Этот метод не устарел, но его нужно использовать с осторожностью: он не учитывает ориентацию устройства (если вы не подписались на уведомления об изменении ориентации).
2. Для получения размера с учетом текущей ориентации:
// Внутри UIViewController
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let currentBounds = view.bounds
print("Размер вью с учетом ориентации: \(currentBounds.size)")
}
Лучший способ — использовать view.bounds внутри контроллера. Это автоматически обновляется при повороте устройства и учитывает safe area (если вы используете safeAreaInsets).
3. Для получения размера с учетом Safe Area:
// Внутри UIViewController
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
let safeAreaBounds = view.bounds.inset(by: view.safeAreaInsets)
print("Доступная область после safe area: \(safeAreaBounds.size)")
}
4. Для ScrollView и UICollectionView:
// Внутри viewDidLoad
let scrollView = UIScrollView(frame: view.bounds)
scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
scrollView.contentSize = CGSize(width: view.bounds.width, height: 2000)
Никогда не задавайте жесткие размеры для ScrollView. Используйте view.bounds или UIScreen.main.bounds только для начальной настройки, а затем обновляйте через Auto Layout.
5. Определение типа устройства (iPhone/iPad):
if UIDevice.current.userInterfaceIdiom == .phone {
print("Это iPhone")
} else if UIDevice.current.userInterfaceIdiom == .pad {
print("Это iPad")
}
6. Получение размера в пикселях (для графики):
let screenScale = UIScreen.main.scale
let pixelWidth = screenBounds.width * screenScale
let pixelHeight = screenBounds.height * screenScale
print("Размер в пикселях: \(pixelWidth) x \(pixelHeight)")
Рекомендации
- Не используйте
UIApplication.shared.keyWindow— это deprecated с iOS 13. ИспользуйтеUIWindowSceneилиview.window. - Для адаптивной верстки всегда используйте Auto Layout и Size Classes вместо жестких расчетов размеров.
- Для получения размеров вью дождитесь загрузки (viewDidLayoutSubviews или viewWillAppear).
- Избегайте использования
UIScreen.mainв многоконных приложениях (iPadOS) — используйтеview.window?.windowScene?.screen.
Пример полного решения для современного iOS приложения:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Начальная настройка
setupUI()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Обновление размеров после изменения ориентации
updateLayoutForCurrentSize()
}
private func setupUI() {
let label = UILabel()
label.text = "Размер экрана: \(UIScreen.main.bounds.size)"
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
private func updateLayoutForCurrentSize() {
print("Текущий размер вью: \(view.bounds.size)")
print("Safe area insets: \(view.safeAreaInsets)")
}
}
Этот подход гарантирует, что вы получите корректные размеры в любой ситуации, включая многозадачность на iPad и Dynamic Island на iPhone 14 Pro.
<<Альтернативный подход: использование UIScreen.main.nativeBounds
Если вам нужен точный физический размер экрана в пикселях (а не в точках), используйте nativeBounds. Это особенно полезно для работы с камерой, Metal или Core Graphics.
let nativeBounds = UIScreen.main.nativeBounds
print("Физический размер в пикселях: \(nativeBounds.size)")
// Соотношение сторон
let aspectRatio = nativeBounds.width / nativeBounds.height
print("Соотношение сторон: \(aspectRatio)")
Важно: nativeBounds всегда возвращает размер в портретной ориентации, даже если устройство повернуто. Для получения текущей ориентации используйте UIScreen.main.bounds или view.bounds.
Определение конкретной модели устройства
Иногда проще определить модель по размеру экрана, чем адаптировать верстку:
enum DeviceModel {
case iPhoneSE, iPhoneStandard, iPhonePlus, iPhoneProMax, iPad
static var current: DeviceModel {
let height = max(UIScreen.main.bounds.width, UIScreen.main.bounds.height)
switch height {
case 568: return .iPhoneSE // iPhone SE (1st gen)
case 667: return .iPhoneStandard // iPhone 6,7,8
case 736: return .iPhonePlus // iPhone 6+,7+,8+
case 812: return .iPhoneProMax // iPhone X, XS, 11 Pro
case 896: return .iPhoneProMax // iPhone XR, 11, 12
default: return .iPad
}
}
}
print("Текущая модель: \(DeviceModel.current)")
Этот подход менее гибкий, чем Auto Layout, но может быть полезен для быстрых прототипов или специфических настроек (например, для разных разрешений изображений).
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги