What is the equivalent of UI_USER_INTERFACE_IDIOM()
in Swift to detect between iPhone and iPad?
I get an Use of unresolved identifier
error when compiling in Swift.
When working with Swift, you can use the enum
UIUserInterfaceIdiom
, defined as:
enum UIUserInterfaceIdiom : Int {
case unspecified
case phone // iPhone and iPod touch style UI
case pad // iPad style UI (also includes macOS Catalyst)
}
So you can use it as:
UIDevice.current.userInterfaceIdiom == .pad
UIDevice.current.userInterfaceIdiom == .phone
UIDevice.current.userInterfaceIdiom == .unspecified
Or with a Switch statement:
switch UIDevice.current.userInterfaceIdiom {
case .phone:
// It's an iPhone
case .pad:
// It's an iPad (or macOS Catalyst)
@unknown default:
// Uh, oh! What could it be?
}
UI_USER_INTERFACE_IDIOM()
is an Objective-C macro, which is defined as:
#define UI_USER_INTERFACE_IDIOM() \ ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] ? \ [[UIDevice currentDevice] userInterfaceIdiom] : \ UIUserInterfaceIdiomPhone)
Also, note that even when working with Objective-C, the UI_USER_INTERFACE_IDIOM()
macro is only required when targeting iOS 3.2 and below. When deploying to iOS 3.2 and up, you can use [UIDevice userInterfaceIdiom]
directly.
if UIDevice.currentDevice().userInterfaceIdiom == .Pad
Jun 12, 2014 at 13:09
UIDevice.currentDevice().userInterfaceIdiom
becomes UIDevice.current.userInterfaceIdiom
Feb 6, 2017 at 16:49
You should use this GBDeviceInfo framework or ...
Apple defines this:
public enum UIUserInterfaceIdiom : Int {
case unspecified
case phone // iPhone and iPod touch style UI
case pad // iPad style UI
@available(iOS 9.0, *)
case tv // Apple TV style UI
@available(iOS 9.0, *)
case carPlay // CarPlay style UI
}
so for the strict definition of the device can be used this code
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_7 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6P_7P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
}
how to use
if DeviceType.IS_IPHONE_6P_7P {
print("IS_IPHONE_6P_7P")
}
to detect iOS version
struct Version{
static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
static let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)
static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
}
how to use
if Version.iOS8 {
print("iOS8")
}
struct ScreenSize/DeviceType
approach since it works in Simulator
Jun 2, 2015 at 10:40
if/else case:
if UIDevice.current.userInterfaceIdiom == .pad {
// iPad
} else {
// not iPad (iPhone, mac, tv, carPlay, unspecified)
}
Swift 2.0 & iOS 9 & Xcode 7.1
// 1. request an UITraitCollection instance
let deviceIdiom = UIScreen.mainScreen().traitCollection.userInterfaceIdiom
// 2. check the idiom
switch (deviceIdiom) {
case .Pad:
print("iPad style UI")
case .Phone:
print("iPhone and iPod touch style UI")
case .TV:
print("tvOS style UI")
default:
print("Unspecified UI idiom")
}
Swift 3.0 and Swift 4.0
// 1. request an UITraitCollection instance
let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom
// 2. check the idiom
switch (deviceIdiom) {
case .pad:
print("iPad style UI")
case .phone:
print("iPhone and iPod touch style UI")
case .tv:
print("tvOS style UI")
default:
print("Unspecified UI idiom")
}
Use UITraitCollection. The iOS trait environment is exposed though the traitCollection property of the UITraitEnvironment protocol. This protocol is adopted by the following classes:
I do in that way:
UIDevice.current.model
It shows the name of the device.
To check if is iPad or iPhone:
if ( UIDevice.current.model.range(of: "iPad") != nil){
print("I AM IPAD")
} else {
print("I AM IPHONE")
}
Swift 4.2 - 5.1 Extension
public extension UIDevice {
class var isPhone: Bool {
return UIDevice.current.userInterfaceIdiom == .phone
}
class var isPad: Bool {
return UIDevice.current.userInterfaceIdiom == .pad
}
class var isTV: Bool {
return UIDevice.current.userInterfaceIdiom == .tv
}
class var isCarPlay: Bool {
return UIDevice.current.userInterfaceIdiom == .carPlay
}
}
Usage
if UIDevice.isPad {
// Do something
}
Try adding an extension like this:
public extension UIDevice {
var modelName: String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8 where value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
switch identifier {
case "iPod5,1": return "iPod Touch 5"
case "iPod7,1": return "iPod Touch 6"
case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4"
case "iPhone4,1": return "iPhone 4s"
case "iPhone5,1", "iPhone5,2": return "iPhone 5"
case "iPhone5,3", "iPhone5,4": return "iPhone 5c"
case "iPhone6,1", "iPhone6,2": return "iPhone 5s"
case "iPhone7,2": return "iPhone 6"
case "iPhone7,1": return "iPhone 6 Plus"
case "iPhone8,1": return "iPhone 6s"
case "iPhone8,2": return "iPhone 6s Plus"
case "iPhone9,1", "iPhone9,3": return "iPhone 7"
case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus"
case "iPhone8,4": return "iPhone SE"
case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2"
case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad 3"
case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad 4"
case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air"
case "iPad5,3", "iPad5,4": return "iPad Air 2"
case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad Mini"
case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad Mini 2"
case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad Mini 3"
case "iPad5,1", "iPad5,2": return "iPad Mini 4"
case "iPad6,3", "iPad6,4", "iPad6,7", "iPad6,8":return "iPad Pro"
case "AppleTV5,3": return "Apple TV"
case "i386", "x86_64": return "Simulator"
default: return identifier
}
}
}
This is how you will use it:
let modelName = UIDevice.currentDevice().modelName
EDIT For simulator, you can try a solution here
Swift 2.x:
Adding to Beslav Turalov answer's the new entry iPad Pro can easily be find with this line
to detect iPad Pro
struct DeviceType
{
...
static let IS_IPAD_PRO = UIDevice.currentDevice().userInterfaceIdiom == .Pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
}
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE = UIDevice.current.userInterfaceIdiom == .phone
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPHONE_7 = IS_IPHONE_6
static let IS_IPHONE_7P = IS_IPHONE_6P
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO_9_7 = IS_IPAD
static let IS_IPAD_PRO_12_9 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
static let IS_TV = UIDevice.current.userInterfaceIdiom == .tv
static let IS_CAR_PLAY = UIDevice.current.userInterfaceIdiom == .carPlay
}
struct Version{
static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
static let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)
static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0 && Version.SYS_VERSION_FLOAT < 11.0)
}
USAGE:
if DeviceType.IS_IPHONE_7P { print("iPhone 7 plus") }
if DeviceType.IS_IPAD_PRO_9_7 && Version.iOS10 { print("iPad pro 9.7 with iOS 10 version") }
In swift 4 & Xcode 9.2 , you can detect if a device is iPhone/iPad by below ways.
if (UIDevice.current.userInterfaceIdiom == .pad){
print("iPad")
}
else{
print("iPhone")
}
Another Way
let deviceName = UIDevice.current.model
print(deviceName);
if deviceName == "iPhone"{
print("iPhone")
}
else{
print("iPad")
}
Try this for check current device is iPhone or iPad:
Swift 5
struct Device {
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad
static let IS_IPHONE = UIDevice.current.userInterfaceIdiom == .phone
}
Use:
if(Device.IS_IPHONE){
// device is iPhone
}if(Device.IS_IPAD){
// device is iPad (or a Mac running under macOS Catalyst)
}else{
// other
}
Since iOS 13, UI_USER_INTERFACE_IDIOM
has been deprecated. If your code is still in Obj-C
, you can use the following:
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
// device is iPad
}
Where:
typedef NS_ENUM(NSInteger, UIUserInterfaceIdiom) {
UIUserInterfaceIdiomUnspecified = -1,
UIUserInterfaceIdiomPhone API_AVAILABLE(ios(3.2)), // iPhone and iPod touch style UI
UIUserInterfaceIdiomPad API_AVAILABLE(ios(3.2)), // iPad style UI
UIUserInterfaceIdiomTV API_AVAILABLE(ios(9.0)), // Apple TV style UI
UIUserInterfaceIdiomCarPlay API_AVAILABLE(ios(9.0)), // CarPlay style UI
};
Thank you everybody support :))
UIDevice+Extensions.swift
import Foundation
import UIKit
extension UIDevice {
static let modelName: String = {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
func mapToDevice(identifier: String) -> String { // swiftlint:disable:this cyclomatic_complexity
#if os(iOS)
switch identifier {
case "iPod5,1": return "iPod Touch 5"
case "iPod7,1": return "iPod Touch 6"
case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4"
case "iPhone4,1": return "iPhone 4s"
case "iPhone5,1", "iPhone5,2": return "iPhone 5"
case "iPhone5,3", "iPhone5,4": return "iPhone 5c"
case "iPhone6,1", "iPhone6,2": return "iPhone 5s"
case "iPhone7,2": return "iPhone 6"
case "iPhone7,1": return "iPhone 6 Plus"
case "iPhone8,1": return "iPhone 6s"
case "iPhone8,2": return "iPhone 6s Plus"
case "iPhone9,1", "iPhone9,3": return "iPhone 7"
case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus"
case "iPhone8,4": return "iPhone SE"
case "iPhone10,1", "iPhone10,4": return "iPhone 8"
case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus"
case "iPhone10,3", "iPhone10,6": return "iPhone X"
case "iPhone11,2": return "iPhone XS"
case "iPhone11,4", "iPhone11,6": return "iPhone XS Max"
case "iPhone11,8": return "iPhone XR"
case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2"
case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad 3"
case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad 4"
case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air"
case "iPad5,3", "iPad5,4": return "iPad Air 2"
case "iPad6,11", "iPad6,12": return "iPad 5"
case "iPad7,5", "iPad7,6": return "iPad 6"
case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad Mini"
case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad Mini 2"
case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad Mini 3"
case "iPad5,1", "iPad5,2": return "iPad Mini 4"
case "iPad6,3", "iPad6,4": return "iPad Pro 9.7 Inch"
case "iPad6,7", "iPad6,8": return "iPad Pro 12.9 Inch"
case "iPad7,1", "iPad7,2": return "iPad Pro 12.9 Inch 2. Generation"
case "iPad7,3", "iPad7,4": return "iPad Pro 10.5 Inch"
case "AppleTV5,3": return "Apple TV"
case "AppleTV6,2": return "Apple TV 4K"
case "AudioAccessory1,1": return "HomePod"
case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))"
default: return identifier
}
#elseif os(tvOS)
switch identifier {
case "AppleTV5,3": return "Apple TV 4"
case "AppleTV6,2": return "Apple TV 4K"
case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))"
default: return identifier
}
#endif
}
return mapToDevice(identifier: identifier)
}()
}
enum DeviceName: String {
case iPod_Touch_5 = "iPod Touch 5"
case pod_Touch_6 = "Pod Touch 6"
case iPhone_4 = "iPhone 4"
case iPhone_4s = "iPhone 4s"
case iPhone_5 = "iPhone 5"
case iPhone_5c = "iPhone 5c"
case iPhone_5s = "iPhone 5s"
case iPhone_6 = "iPhone 6"
case iPhone_6_Plus = "iPhone 6 Plus"
case iPhone_6s = "iPhone 6s"
case iPhone_6s_Plus = "iPhone 6s Plus"
case iPhone_7 = "iPhone 7"
case iPhone_7_Plus = "iPhone 7 Plus"
case iPhone_SE = "iPhone SE"
case iPhone_8 = "iPhone 8"
case iPhone_8_Plus = "iPhone 8 Plus"
case iPhone_X = "iPhone X"
case iPhone_XS = "iPhone XS"
case iPhone_XS_Max = "iPhone XS Max"
case iPhone_XR = "iPhone XR"
case iPad_2 = "iPad 2"
case iPad_3 = "iPad 3"
case iPad_4 = "iPad 4"
case iPad_Air = "iPad Air"
case iPad_Air_2 = "iPad Air 2"
case iPad_5 = "iPad 5"
case iPad_6 = "iPad 6"
case iPad_Mini = "iPad Mini"
case iPad_Mini_2 = "iPad Mini 2"
case iPad_Mini_3 = "iPad Mini 3"
case iPad_Mini_4 = "iPad Mini 4"
case iPad_Pro_9_7_Inch = "iPad Pro 9.7 Inch"
case iPad_Pro_12_9_Inch = "iPad Pro 12.9 Inch"
case iPad_Pro_12_9_Inch_2_Generation = "iPad Pro 12.9 Inch 2. Generation"
case iPad_Pro_10_5_Inch = "iPad Pro 10.5 Inch"
case apple_TV = "Apple TV"
case apple_TV_4K = "Apple TV 4K"
case homePod = "HomePod"
}
SharedFunctions.swift
import Foundation
import UIKit
func isDevice(_ name: DeviceName) -> Bool {
let modelName = UIDevice.modelName.replacingOccurrences(of: "Simulator", with: "").trimmed()
if name.rawValue == modelName {
return true
}
return false
}
String+Whitespace.swift
import Foundation
extension String {
public func trimmed() -> String {
return self.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
Swift 2.0 & iOS 7+ / iOS 8+ / iOS 9+
public class Helper {
public class var isIpad:Bool {
if #available(iOS 8.0, *) {
return UIScreen.mainScreen().traitCollection.userInterfaceIdiom == .Pad
} else {
return UIDevice.currentDevice().userInterfaceIdiom == .Pad
}
}
public class var isIphone:Bool {
if #available(iOS 8.0, *) {
return UIScreen.mainScreen().traitCollection.userInterfaceIdiom == .Phone
} else {
return UIDevice.currentDevice().userInterfaceIdiom == .Phone
}
}
}
Use :
if Helper.isIpad {
}
OR
guard Helper.isIpad else {
return
}
Thanks @user3378170
FYI, I have used UI_USER_INTERFACE_IDIOM()
for my app written in Swift. The app can be compiled well with XCode 6.3.1 without any warning on that command, runs well on Simulator (with any selected devices) and on all my real devices (iPhone, iPad) with iOS versions from 7.1 to 8.3.
However, the app crashed on Apple reviewers' devices (and was refused). That took me few days to detect the problem with few more re-uploads to iTunes Connect.
Now I use UIDevice.currentDevice().userInterfaceIdiom
instead and my app can survive from such crashes.
If you want to check the current device whether its iPad or iPhone then you can use these line of code :
if(UIDevice.currentDevice().userInterfaceIdiom == .Pad){
}else if(UIDevice.currentDevice().userInterfaceIdiom == .Phone){
}
Swift 3.0:
let userInterface = UIDevice.current.userInterfaceIdiom
if(userInterface == .pad){
//iPads
}else if(userInterface == .phone){
//iPhone
}else if(userInterface == .carPlay){
//CarPlay
}else if(userInterface == .tv){
//AppleTV
}
Made a couple of additions to the above answers so that you get returned a type instead of string value.
I figured that this is primarily going to be used for UI adjustments so I didn't think it relevant to include all the sub models i.e. iPhone 5s but this could be easily extended by adding in model tests to the isDevice Array
Tested working in Swift 3.1 Xcode 8.3.2 with physical and simulator devices
Implementation:
UIDevice.whichDevice()
public enum SVNDevice {
case isiPhone4, isIphone5, isIphone6or7, isIphone6por7p, isIphone, isIpad, isIpadPro
}
extension UIDevice {
class func whichDevice() -> SVNDevice? {
let isDevice = { (comparision: Array<(Bool, SVNDevice)>) -> SVNDevice? in
var device: SVNDevice?
comparision.forEach({
device = $0.0 ? $0.1 : device
})
return device
}
return isDevice([
(UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0, SVNDevice.isiPhone4),
(UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0, SVNDevice.isIphone5),
(UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0, SVNDevice.isIphone6or7),
(UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0, SVNDevice.isIphone6por7p),
(UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0, SVNDevice.isIpad),
(UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0, SVNDevice.isIpadPro)])
}
}
private struct ScreenSize {
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
I've created a framework called SVNBootstaper which includes this and some other helper protocols, it's public and available through Carthage.
You can use the new way on Swift 5:
switch traitCollection.userInterfaceIdiom {
case .unspecified:
// do something
case .phone:
// do something
case .pad:
// do something
case .tv:
// do something
case .carPlay:
// do something
case .mac:
// do something
@unknown default:
// do something
}