Detect current device with UI_USER_INTERFACE_IDIOM() in Swift
Solution 1
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.
Solution 2
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")
}
Solution 3
if/else case:
if UIDevice.current.userInterfaceIdiom == .pad {
// iPad
} else {
// not iPad (iPhone, mac, tv, carPlay, unspecified)
}
Solution 4
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:
- UIScreen
- UIWindow
- UIViewController
- UIPresentationController
- UIView
Solution 5
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")
}
Related videos on Youtube
Berry Blue
Updated on July 08, 2022Comments
-
Berry Blue almost 2 years
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. -
Mihai Fratu almost 10 yearsNever mind. I got it working with
if UIDevice.currentDevice().userInterfaceIdiom == .Pad
-
Zmey almost 9 yearsAs Tony mentioned in one of the answers below, UI_USER_INTERFACE_IDIOM in Swift apps crashes when the app is deployed via TestFlight. Strangely, it works when the app is uploaded directly to device from X-Code. I've also hit this bug.
-
Peacemoon almost 9 years@Zmey Yes, my app has also got rejected because UI_USER_INTERFACE_IDIOM crashes in review, very strange
-
SoftDesigner almost 9 yearsI like
struct ScreenSize/DeviceType
approach since it works in Simulator -
Praveen almost 9 yearsExactly correct. It does crash and caused me a lot of headache trying to figure out the issue.
-
Computerspezl almost 9 yearsThanks a lot. I struggled over this bug when a new version of my app was released and crashed from the App Store, but never before, when it was installed over XCode. Hopefully I'll get an expedited review for the fix.
-
Luca Davanzo almost 9 yearsdefinitely best solution, for me at least. Check for userInterfaceIdiom has a problem: if your app is for iPhone only but you launch app on iPad, userInterfaceIdiom is == .Phone
-
tschoffelen over 8 yearsThe Swift compiler kept crashing whenever I used UI_USER_INTERFACE_IDIOM() in my code, without any error message. Very strange.
-
YannSteph over 8 yearsThanks @user3378170 for iOS 9
-
Ashoor over 8 yearsapproved answer should go to this neat answer
-
davew over 8 yearsfwiw, Apple's doc now states "If your app runs in iOS 3.2 and later, use userInterfaceIdiom instead."
-
webcpu over 8 yearsIf you use UIDevice.currentDevice() in swift, Xcode 7 will report an error, "LLVM ERROR: Broken module found, compilation aborted!". There is a work-around, you can add the function below to your objective-c bridging header file and use currentDevice() instead. static UIDevice* currentDevice() { return [UIDevice currentDevice]; }
-
webcpu over 8 yearspublic enum UIUserInterfaceIdiom : Int { case Unspecified @available(iOS 3.2, *) case Phone // iPhone and iPod touch style UI @available(iOS 3.2, *) case Pad // iPad style UI @available(iOS 9.0, *) case TV // Apple TV style UI } Check out the definition of UIUserInterfaceIdiom.If it's not Pad, it could be Phone, TV, Unspecified.
-
NoodleOfDeath about 8 yearsIs it recommended to use this type of switch case in production when making a universal app inside local scope? Or should you make completely separate class implementations based on the device interface?
-
swiftBoy almost 8 yearsHuge love from INDIA, appreciate you efforts, Thanks you so much for sharing and making better Stackoverflow ;)
-
Fattie almost 8 yearsDefinitely the best solution. Good one.
-
Vaibhav Jhaveri over 7 yearsWhat's the updated code? In context to DEVICE_TYPE for iPhone 7 and 7P
-
Steve over 7 yearsnice, though testing with simulator just returns simulator. is there a way around this?
-
Sea Coast of Tibet over 7 yearsIn Swift 3
UIDevice.currentDevice().userInterfaceIdiom
becomesUIDevice.current.userInterfaceIdiom
-
Randall Wang almost 7 yearsIf your app is iPhone only, this method will not work correctly, you will always get .phone, check Ricardo's answer.
-
Rahul Iyer about 4 yearsWhat is the equivalent way to do this with SwiftUI ? Since the above requires UIKit ? stackoverflow.com/questions/61113923/…
-
Ethan Allen about 3 yearsThank you for the Obj-C answer.
-
Sayalee Pote almost 3 yearsMore Obj-C aligned writing - [[UIDevice currentDevice] userInterfaceIdiom]
-
Eric Aya about 2 yearsThis is not new in Swift 5, and has already been posted, here for example.