Detect current device with UI_USER_INTERFACE_IDIOM() in Swift

179,153

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")
}
Share:
179,153

Related videos on Youtube

Berry Blue
Author by

Berry Blue

Updated on July 08, 2022

Comments

  • Berry Blue
    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
    Mihai Fratu almost 10 years
    Never mind. I got it working with if UIDevice.currentDevice().userInterfaceIdiom == .Pad
  • Zmey
    Zmey almost 9 years
    As 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
    Peacemoon almost 9 years
    @Zmey Yes, my app has also got rejected because UI_USER_INTERFACE_IDIOM crashes in review, very strange
  • SoftDesigner
    SoftDesigner almost 9 years
    I like struct ScreenSize/DeviceType approach since it works in Simulator
  • Praveen
    Praveen almost 9 years
    Exactly correct. It does crash and caused me a lot of headache trying to figure out the issue.
  • Computerspezl
    Computerspezl almost 9 years
    Thanks 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
    Luca Davanzo almost 9 years
    definitely 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
    tschoffelen over 8 years
    The Swift compiler kept crashing whenever I used UI_USER_INTERFACE_IDIOM() in my code, without any error message. Very strange.
  • YannSteph
    YannSteph over 8 years
    Thanks @user3378170 for iOS 9
  • Ashoor
    Ashoor over 8 years
    approved answer should go to this neat answer
  • davew
    davew over 8 years
    fwiw, Apple's doc now states "If your app runs in iOS 3.2 and later, use userInterfaceIdiom instead."
  • webcpu
    webcpu over 8 years
    If 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
    webcpu over 8 years
    public 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
    NoodleOfDeath about 8 years
    Is 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
    swiftBoy almost 8 years
    Huge love from INDIA, appreciate you efforts, Thanks you so much for sharing and making better Stackoverflow ;)
  • Fattie
    Fattie almost 8 years
    Definitely the best solution. Good one.
  • Vaibhav Jhaveri
    Vaibhav Jhaveri over 7 years
    What's the updated code? In context to DEVICE_TYPE for iPhone 7 and 7P
  • Steve
    Steve over 7 years
    nice, though testing with simulator just returns simulator. is there a way around this?
  • Sea Coast of Tibet
    Sea Coast of Tibet over 7 years
    In Swift 3 UIDevice.currentDevice().userInterfaceIdiom becomes UIDevice.current.userInterfaceIdiom
  • Randall Wang
    Randall Wang almost 7 years
    If your app is iPhone only, this method will not work correctly, you will always get .phone, check Ricardo's answer.
  • Rahul Iyer
    Rahul Iyer about 4 years
    What is the equivalent way to do this with SwiftUI ? Since the above requires UIKit ? stackoverflow.com/questions/61113923/…
  • Ethan Allen
    Ethan Allen about 3 years
    Thank you for the Obj-C answer.
  • Sayalee Pote
    Sayalee Pote almost 3 years
    More Obj-C aligned writing - [[UIDevice currentDevice] userInterfaceIdiom]
  • Eric Aya
    Eric Aya about 2 years
    This is not new in Swift 5, and has already been posted, here for example.