Определение типа устройства (iPhone/iPad) в Swift: UI_USER_INTERFACE_IDIOM() и альтернативы
Всем привет! Я только начал изучать Swift и столкнулся с проблемой при определении типа устройства (iPhone или iPad). В старых проектах на Objective-C я видел макрос UI_USER_INTERFACE_IDIOM(), но в Swift он не работает напрямую.
Мне нужно написать код, который будет по-разному вести себя на iPad и iPhone. Например, на iPad я хочу показывать контроллер как UISplitViewController, а на iPhone — как обычный UINavigationController.
Вот что я пробовал, но это не компилируется:
if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad {
// iPad
} else {
// iPhone
}
Xcode выдаёт ошибку: "Use of unresolved identifier 'UI_USER_INTERFACE_IDIOM'". Как правильно определить тип устройства в Swift? Есть ли более современный способ, чем этот старый макрос? Заранее спасибо!
<<Правильный способ определения типа устройства в Swift
В Swift макрос UI_USER_INTERFACE_IDIOM() из Objective-C недоступен, но есть несколько эквивалентных и более современных решений. Вот основной подход через свойство UIDevice.current.userInterfaceIdiom.
Базовое использование
import UIKit
if UIDevice.current.userInterfaceIdiom == .pad {
print("Это iPad")
} else if UIDevice.current.userInterfaceIdiom == .phone {
print("Это iPhone")
} else {
print("Другое устройство (например, iPod touch или Apple TV)")
}
Пример с UISplitViewController
Вот как можно реализовать адаптивное поведение, которое вы описали:
func configureInitialViewController() {
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
// На iPad используем SplitViewController
let splitVC = mainStoryboard.instantiateViewController(withIdentifier: "SplitViewController")
window?.rootViewController = splitVC
} else {
// На iPhone используем NavigationController
let navVC = mainStoryboard.instantiateViewController(withIdentifier: "NavigationController")
window?.rootViewController = navVC
}
}
Дополнительные возможности
Иногда нужно проверить не только тип устройства, но и его ориентацию или размер экрана:
// Проверка на iPad в альбомной ориентации
if UIDevice.current.userInterfaceIdiom == .pad &&
UIDevice.current.orientation.isLandscape {
print("iPad в альбомной ориентации")
}
// Использование trait collections (рекомендуется для адаптивного дизайна)
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.horizontalSizeClass == .regular &&
traitCollection.verticalSizeClass == .regular {
print("Большой экран (обычно iPad)")
}
}
Почему не работает UI_USER_INTERFACE_IDIOM()?
- Это макрос из Objective-C, который не импортируется в Swift автоматически.
- В Swift используется более безопасный и типизированный подход через
UIDevice. - Макрос возвращает
UIUserInterfaceIdiom(enum), который в Swift доступен какUIUserInterfaceIdiomс значениями.phone,.pad,.tv,.carPlayи.unspecified.
Советы для начинающих
- Всегда используйте
UIDevice.current.userInterfaceIdiom— это стандартный способ в Swift. - Для адаптивного интерфейса предпочтительнее использовать
traitCollectionилиsize classes. - Не забывайте импортировать
UIKit, так какUIDeviceявляется его частью.
Альтернативный подход: использование traitCollection
Вместо прямой проверки типа устройства, Apple рекомендует использовать trait collections и size classes. Это более гибкий подход, который работает не только с iPhone/iPad, но и с разными размерами экранов (например, iPad в режиме Split View или iPhone SE).
// Проверка через traitCollection
if traitCollection.horizontalSizeClass == .regular &&
traitCollection.verticalSizeClass == .regular {
print("Устройство с большим экраном (iPad или iPhone Plus в альбоме)")
} else {
print("Устройство с компактным экраном")
}
// Адаптивный layout с помощью UIUserInterfaceSizeClass
override func willTransition(to newCollection: UITraitCollection,
with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
if newCollection.horizontalSizeClass == .compact {
showCompactLayout()
} else {
showRegularLayout()
}
}
Преимущества:
- Код работает корректно на всех устройствах, включая iPad в режиме Split View.
- Не привязывается к конкретному типу устройства, что делает приложение более универсальным.
- Лучше подходит для адаптивных интерфейсов в SwiftUI и UIKit.
Используйте UIDevice.current.userInterfaceIdiom только когда вам действительно нужно знать тип устройства (например, для аналитики или выбора специфических жестов). Для layout всегда предпочтительнее traitCollection.