How to determine the current iPhone/device model?

333,425

Solution 1

I made this "pure Swift" extension on UIDevice.

If you are looking for a more elegant solution you can use my µ-framework DeviceKit published on GitHub (also available via CocoaPods, Carthage and Swift Package Manager).

Here's the code:

import UIKit

public 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 (5th generation)"
            case "iPod7,1":                                       return "iPod touch (6th generation)"
            case "iPod9,1":                                       return "iPod touch (7th generation)"
            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 "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 "iPhone12,1":                                    return "iPhone 11"
            case "iPhone12,3":                                    return "iPhone 11 Pro"
            case "iPhone12,5":                                    return "iPhone 11 Pro Max"
            case "iPhone13,1":                                    return "iPhone 12 mini"
            case "iPhone13,2":                                    return "iPhone 12"
            case "iPhone13,3":                                    return "iPhone 12 Pro"
            case "iPhone13,4":                                    return "iPhone 12 Pro Max"
            case "iPhone14,4":                                    return "iPhone 13 mini"
            case "iPhone14,5":                                    return "iPhone 13"
            case "iPhone14,2":                                    return "iPhone 13 Pro"
            case "iPhone14,3":                                    return "iPhone 13 Pro Max"
            case "iPhone8,4":                                     return "iPhone SE"
            case "iPhone12,8":                                    return "iPhone SE (2nd generation)"
            case "iPhone14,6":                                    return "iPhone SE (3rd generation)"
            case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":      return "iPad 2"
            case "iPad3,1", "iPad3,2", "iPad3,3":                 return "iPad (3rd generation)"
            case "iPad3,4", "iPad3,5", "iPad3,6":                 return "iPad (4th generation)"
            case "iPad6,11", "iPad6,12":                          return "iPad (5th generation)"
            case "iPad7,5", "iPad7,6":                            return "iPad (6th generation)"
            case "iPad7,11", "iPad7,12":                          return "iPad (7th generation)"
            case "iPad11,6", "iPad11,7":                          return "iPad (8th generation)"
            case "iPad12,1", "iPad12,2":                          return "iPad (9th generation)"
            case "iPad4,1", "iPad4,2", "iPad4,3":                 return "iPad Air"
            case "iPad5,3", "iPad5,4":                            return "iPad Air 2"
            case "iPad11,3", "iPad11,4":                          return "iPad Air (3rd generation)"
            case "iPad13,1", "iPad13,2":                          return "iPad Air (4th generation)"
            case "iPad13,16", "iPad13,17":                        return "iPad Air (5th generation)"
            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 "iPad11,1", "iPad11,2":                          return "iPad mini (5th generation)"
            case "iPad14,1", "iPad14,2":                          return "iPad mini (6th generation)"
            case "iPad6,3", "iPad6,4":                            return "iPad Pro (9.7-inch)"
            case "iPad7,3", "iPad7,4":                            return "iPad Pro (10.5-inch)"
            case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":      return "iPad Pro (11-inch) (1st generation)"
            case "iPad8,9", "iPad8,10":                           return "iPad Pro (11-inch) (2nd generation)"
            case "iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7":  return "iPad Pro (11-inch) (3rd generation)"
            case "iPad6,7", "iPad6,8":                            return "iPad Pro (12.9-inch) (1st generation)"
            case "iPad7,1", "iPad7,2":                            return "iPad Pro (12.9-inch) (2nd generation)"
            case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":      return "iPad Pro (12.9-inch) (3rd generation)"
            case "iPad8,11", "iPad8,12":                          return "iPad Pro (12.9-inch) (4th generation)"
            case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11":return "iPad Pro (12.9-inch) (5th generation)"
            case "AppleTV5,3":                                    return "Apple TV"
            case "AppleTV6,2":                                    return "Apple TV 4K"
            case "AudioAccessory1,1":                             return "HomePod"
            case "AudioAccessory5,1":                             return "HomePod mini"
            case "i386", "x86_64", "arm64":                       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)
    }()

}

You call it like this:

let modelName = UIDevice.modelName

For real devices it returns e.g. "iPad Pro (12.9-inch) (5th generation)", for simulators it returns e.g. "Simulator iPad Pro (12.9-inch) (5th generation)"

Here's the model references:

Solution 2

Swift 5.x, both device & simulator updated to 2022

with the last: iPhone SE 3rd generation 2022, iPad Air 5th generation, iPhone 13 (all models), iPad 9th generation 2021, iPad mini 6th generation 2021, Apple Watch Series 7, iPad Pro (11-inch) (3rd generation), iPad Pro (12.9-inch) (5th generation) and Apple TV 4K (2nd generation) , (updates also for all iPods, Apple Watches and Apple TVs)

This method detects the correct model even if it's a simulator. (The exact name for the simulator device model running in your simulator)

With this answer you can check multiple device in few lines thanks to the enums

example:

var myDefaultFontSize: CGFloat = 26.0
switch UIDevice().type {
    case .iPhoneSE, .iPhone5, .iPhone5S: print("default value")
    case .iPhone6, .iPhone7, .iPhone8, .iPhone6S, .iPhoneX: myDefaultFontSize += 4
    default: break
}

This is the code:

public enum Model : String {

//Simulator
case simulator     = "simulator/sandbox",

//iPod
iPod1              = "iPod 1",
iPod2              = "iPod 2",
iPod3              = "iPod 3",
iPod4              = "iPod 4",
iPod5              = "iPod 5",
iPod6              = "iPod 6",
iPod7              = "iPod 7",

//iPad
iPad2              = "iPad 2",
iPad3              = "iPad 3",
iPad4              = "iPad 4",
iPadAir            = "iPad Air ",
iPadAir2           = "iPad Air 2",
iPadAir3           = "iPad Air 3",
iPadAir4           = "iPad Air 4",
iPadAir5           = "iPad Air 5",
iPad5              = "iPad 5", //iPad 2017
iPad6              = "iPad 6", //iPad 2018
iPad7              = "iPad 7", //iPad 2019
iPad8              = "iPad 8", //iPad 2020
iPad9              = "iPad 9", //iPad 2021

//iPad Mini
iPadMini           = "iPad Mini",
iPadMini2          = "iPad Mini 2",
iPadMini3          = "iPad Mini 3",
iPadMini4          = "iPad Mini 4",
iPadMini5          = "iPad Mini 5",
iPadMini6          = "iPad Mini 6",

//iPad Pro
iPadPro9_7         = "iPad Pro 9.7\"",
iPadPro10_5        = "iPad Pro 10.5\"",
iPadPro11          = "iPad Pro 11\"",
iPadPro2_11        = "iPad Pro 11\" 2nd gen",
iPadPro3_11        = "iPad Pro 11\" 3rd gen",
iPadPro12_9        = "iPad Pro 12.9\"",
iPadPro2_12_9      = "iPad Pro 2 12.9\"",
iPadPro3_12_9      = "iPad Pro 3 12.9\"",
iPadPro4_12_9      = "iPad Pro 4 12.9\"",
iPadPro5_12_9      = "iPad Pro 5 12.9\"",

//iPhone
iPhone4            = "iPhone 4",
iPhone4S           = "iPhone 4S",
iPhone5            = "iPhone 5",
iPhone5S           = "iPhone 5S",
iPhone5C           = "iPhone 5C",
iPhone6            = "iPhone 6",
iPhone6Plus        = "iPhone 6 Plus",
iPhone6S           = "iPhone 6S",
iPhone6SPlus       = "iPhone 6S Plus",
iPhoneSE           = "iPhone SE",
iPhone7            = "iPhone 7",
iPhone7Plus        = "iPhone 7 Plus",
iPhone8            = "iPhone 8",
iPhone8Plus        = "iPhone 8 Plus",
iPhoneX            = "iPhone X",
iPhoneXS           = "iPhone XS",
iPhoneXSMax        = "iPhone XS Max",
iPhoneXR           = "iPhone XR",
iPhone11           = "iPhone 11",
iPhone11Pro        = "iPhone 11 Pro",
iPhone11ProMax     = "iPhone 11 Pro Max",
iPhoneSE2          = "iPhone SE 2nd gen",
iPhone12Mini       = "iPhone 12 Mini",
iPhone12           = "iPhone 12",
iPhone12Pro        = "iPhone 12 Pro",
iPhone12ProMax     = "iPhone 12 Pro Max",
iPhone13Mini       = "iPhone 13 Mini",
iPhone13           = "iPhone 13",
iPhone13Pro        = "iPhone 13 Pro",
iPhone13ProMax     = "iPhone 13 Pro Max",
iPhoneSE3          = "iPhone SE 3nd gen",

// Apple Watch
AppleWatch1         = "Apple Watch 1gen",
AppleWatchS1        = "Apple Watch Series 1",
AppleWatchS2        = "Apple Watch Series 2",
AppleWatchS3        = "Apple Watch Series 3",
AppleWatchS4        = "Apple Watch Series 4",
AppleWatchS5        = "Apple Watch Series 5",
AppleWatchSE        = "Apple Watch Special Edition",
AppleWatchS6        = "Apple Watch Series 6",
AppleWatchS7        = "Apple Watch Series 7",

//Apple TV
AppleTV1           = "Apple TV 1gen",
AppleTV2           = "Apple TV 2gen",
AppleTV3           = "Apple TV 3gen",
AppleTV4           = "Apple TV 4gen",
AppleTV_4K         = "Apple TV 4K",
AppleTV2_4K        = "Apple TV 4K 2gen",

unrecognized       = "?unrecognized?"
}

// #-#-#-#-#-#-#-#-#-#-#-#-#
// MARK: UIDevice extensions
// #-#-#-#-#-#-#-#-#-#-#-#-#

    public extension UIDevice {
    
    var type: Model {
        var systemInfo = utsname()
        uname(&systemInfo)
        let modelCode = withUnsafePointer(to: &systemInfo.machine) {
            $0.withMemoryRebound(to: CChar.self, capacity: 1) {
                ptr in String.init(validatingUTF8: ptr)
            }
        }
    
        let modelMap : [String: Model] = [
    
            //Simulator
            "i386"      : .simulator,
            "x86_64"    : .simulator,
    
            //iPod
            "iPod1,1"   : .iPod1,
            "iPod2,1"   : .iPod2,
            "iPod3,1"   : .iPod3,
            "iPod4,1"   : .iPod4,
            "iPod5,1"   : .iPod5,
            "iPod7,1"   : .iPod6,
            "iPod9,1"   : .iPod7,
    
            //iPad
            "iPad2,1"   : .iPad2,
            "iPad2,2"   : .iPad2,
            "iPad2,3"   : .iPad2,
            "iPad2,4"   : .iPad2,
            "iPad3,1"   : .iPad3,
            "iPad3,2"   : .iPad3,
            "iPad3,3"   : .iPad3,
            "iPad3,4"   : .iPad4,
            "iPad3,5"   : .iPad4,
            "iPad3,6"   : .iPad4,
            "iPad6,11"  : .iPad5, //iPad 2017
            "iPad6,12"  : .iPad5,
            "iPad7,5"   : .iPad6, //iPad 2018
            "iPad7,6"   : .iPad6,
            "iPad7,11"  : .iPad7, //iPad 2019
            "iPad7,12"  : .iPad7,
            "iPad11,6"  : .iPad8, //iPad 2020
            "iPad11,7"  : .iPad8,
            "iPad12,1"  : .iPad9, //iPad 2021
            "iPad12,2"  : .iPad9,
    
            //iPad Mini
            "iPad2,5"   : .iPadMini,
            "iPad2,6"   : .iPadMini,
            "iPad2,7"   : .iPadMini,
            "iPad4,4"   : .iPadMini2,
            "iPad4,5"   : .iPadMini2,
            "iPad4,6"   : .iPadMini2,
            "iPad4,7"   : .iPadMini3,
            "iPad4,8"   : .iPadMini3,
            "iPad4,9"   : .iPadMini3,
            "iPad5,1"   : .iPadMini4,
            "iPad5,2"   : .iPadMini4,
            "iPad11,1"  : .iPadMini5,
            "iPad11,2"  : .iPadMini5,
            "iPad14,1"  : .iPadMini6,
            "iPad14,2"  : .iPadMini6,
    
            //iPad Pro
            "iPad6,3"   : .iPadPro9_7,
            "iPad6,4"   : .iPadPro9_7,
            "iPad7,3"   : .iPadPro10_5,
            "iPad7,4"   : .iPadPro10_5,
            "iPad6,7"   : .iPadPro12_9,
            "iPad6,8"   : .iPadPro12_9,
            "iPad7,1"   : .iPadPro2_12_9,
            "iPad7,2"   : .iPadPro2_12_9,
            "iPad8,1"   : .iPadPro11,
            "iPad8,2"   : .iPadPro11,
            "iPad8,3"   : .iPadPro11,
            "iPad8,4"   : .iPadPro11,
            "iPad8,9"   : .iPadPro2_11,
            "iPad8,10"  : .iPadPro2_11,
            "iPad13,4"  : .iPadPro3_11,
            "iPad13,5"  : .iPadPro3_11,
            "iPad13,6"  : .iPadPro3_11,
            "iPad13,7"  : .iPadPro3_11,
            "iPad8,5"   : .iPadPro3_12_9,
            "iPad8,6"   : .iPadPro3_12_9,
            "iPad8,7"   : .iPadPro3_12_9,
            "iPad8,8"   : .iPadPro3_12_9,
            "iPad8,11"  : .iPadPro4_12_9,
            "iPad8,12"  : .iPadPro4_12_9,
            "iPad13,8"  : .iPadPro5_12_9,
            "iPad13,9"  : .iPadPro5_12_9,
            "iPad13,10" : .iPadPro5_12_9,
            "iPad13,11" : .iPadPro5_12_9,
    
            //iPad Air
            "iPad4,1"   : .iPadAir,
            "iPad4,2"   : .iPadAir,
            "iPad4,3"   : .iPadAir,
            "iPad5,3"   : .iPadAir2,
            "iPad5,4"   : .iPadAir2,
            "iPad11,3"  : .iPadAir3,
            "iPad11,4"  : .iPadAir3,
            "iPad13,1"  : .iPadAir4,
            "iPad13,2"  : .iPadAir4,
            "iPad13,16" : .iPadAir5,
            "iPad13,17" : .iPadAir5,
    
            //iPhone
            "iPhone3,1" : .iPhone4,
            "iPhone3,2" : .iPhone4,
            "iPhone3,3" : .iPhone4,
            "iPhone4,1" : .iPhone4S,
            "iPhone5,1" : .iPhone5,
            "iPhone5,2" : .iPhone5,
            "iPhone5,3" : .iPhone5C,
            "iPhone5,4" : .iPhone5C,
            "iPhone6,1" : .iPhone5S,
            "iPhone6,2" : .iPhone5S,
            "iPhone7,1" : .iPhone6Plus,
            "iPhone7,2" : .iPhone6,
            "iPhone8,1" : .iPhone6S,
            "iPhone8,2" : .iPhone6SPlus,
            "iPhone8,4" : .iPhoneSE,
            "iPhone9,1" : .iPhone7,
            "iPhone9,3" : .iPhone7,
            "iPhone9,2" : .iPhone7Plus,
            "iPhone9,4" : .iPhone7Plus,
            "iPhone10,1" : .iPhone8,
            "iPhone10,4" : .iPhone8,
            "iPhone10,2" : .iPhone8Plus,
            "iPhone10,5" : .iPhone8Plus,
            "iPhone10,3" : .iPhoneX,
            "iPhone10,6" : .iPhoneX,
            "iPhone11,2" : .iPhoneXS,
            "iPhone11,4" : .iPhoneXSMax,
            "iPhone11,6" : .iPhoneXSMax,
            "iPhone11,8" : .iPhoneXR,
            "iPhone12,1" : .iPhone11,
            "iPhone12,3" : .iPhone11Pro,
            "iPhone12,5" : .iPhone11ProMax,
            "iPhone12,8" : .iPhoneSE2,
            "iPhone13,1" : .iPhone12Mini,
            "iPhone13,2" : .iPhone12,
            "iPhone13,3" : .iPhone12Pro,
            "iPhone13,4" : .iPhone12ProMax,
            "iPhone14,4" : .iPhone13Mini,
            "iPhone14,5" : .iPhone13,
            "iPhone14,2" : .iPhone13Pro,
            "iPhone14,3" : .iPhone13ProMax,
            "iPhone14,6" : .iPhoneSE3,
            
            // Apple Watch
            "Watch1,1" : .AppleWatch1,
            "Watch1,2" : .AppleWatch1,
            "Watch2,6" : .AppleWatchS1,
            "Watch2,7" : .AppleWatchS1,
            "Watch2,3" : .AppleWatchS2,
            "Watch2,4" : .AppleWatchS2,
            "Watch3,1" : .AppleWatchS3,
            "Watch3,2" : .AppleWatchS3,
            "Watch3,3" : .AppleWatchS3,
            "Watch3,4" : .AppleWatchS3,
            "Watch4,1" : .AppleWatchS4,
            "Watch4,2" : .AppleWatchS4,
            "Watch4,3" : .AppleWatchS4,
            "Watch4,4" : .AppleWatchS4,
            "Watch5,1" : .AppleWatchS5,
            "Watch5,2" : .AppleWatchS5,
            "Watch5,3" : .AppleWatchS5,
            "Watch5,4" : .AppleWatchS5,
            "Watch5,9" : .AppleWatchSE,
            "Watch5,10" : .AppleWatchSE,
            "Watch5,11" : .AppleWatchSE,
            "Watch5,12" : .AppleWatchSE,
            "Watch6,1" : .AppleWatchS6,
            "Watch6,2" : .AppleWatchS6,
            "Watch6,3" : .AppleWatchS6,
            "Watch6,4" : .AppleWatchS6,
            "Watch6,6" : .AppleWatchS7,
            "Watch6,7" : .AppleWatchS7,
            "Watch6,8" : .AppleWatchS7,
            "Watch6,9" : .AppleWatchS7,
    
            //Apple TV
            "AppleTV1,1" : .AppleTV1,
            "AppleTV2,1" : .AppleTV2,
            "AppleTV3,1" : .AppleTV3,
            "AppleTV3,2" : .AppleTV3,
            "AppleTV5,3" : .AppleTV4,
            "AppleTV6,2" : .AppleTV_4K,
            "AppleTV11,1" : .AppleTV2_4K
        ]
    
        guard let mcode = modelCode, let map = String(validatingUTF8: mcode), let model = modelMap[map] else { return Model.unrecognized }
        if model == .simulator {
            if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
                if let simMap = String(validatingUTF8: simModelCode), let simModel = modelMap[simMap] {
                    return simModel
                }
            }
        }
        return model
        }
    }

Usage: You can simply get the device model with:

let deviceType = UIDevice().type

or print the exact string with:

print("Running on: \(UIDevice().type)")
Output -> "iPhone X"

Another example with cases:

var myDefaultHeight: CGFloat = 30.0
switch UIDevice().type {
    case .iPhoneSE, .iPhone5, .iPhone5S: print("default value")
    case .iPhone6, .iPhone7, .iPhone8, .iPhone6S, .iPhoneX: myDefaultHeight+= 5
    case .iPhone11, .iPhone12, .iPhone13: myDefaultHeight+= 10
    default: break
}

For Apple devices models visit: https://www.theiphonewiki.com/wiki/Models

P.S.: I've made a little new asyncronous experiment here (direct connection with THEIPHONEWIKI site, without long static device list in source code.

Solution 3

This Swift 3.0 example returns the current device model as an enum constant (to avoid direct comparisons to string literals). The enum's raw value is a String containing the human-readable iOS device name. Since it is Swift, the list of recognized devices only includes models recent enough to support iOS releases that include Swift. The following usage example utilizes the implementation at the end of this answer:

    switch UIDevice().type {
    case .iPhone5:
              print("No TouchID sensor")
    case .iPhone5S:
              fallthrough
    case .iPhone6:
              fallthrough
    case .iPhone6plus:
              fallthrough
    case .iPad_Pro9_7:
              fallthrough
    case .iPad_Pro12_9:
              fallthrough
    case .iPhone7:
              fallthrough
    case .iPhone7plus:
              print("Put your thumb on the " + 
                     UIDevice().type.rawValue + " TouchID sensor")
    case .unrecognized:
              print("Device model unrecognized");
    default:
              print(UIDevice().type.rawValue + " not supported by this app");
    }

Your app should be kept up-to-date for new device releases and also when Apple adds new models for the same device family. For example, iPhone3,1 iPhone3,2 iPhone3,4 are all "iPhone 4". Avoid writing code that doesn't account for new models, so your algorithms don't unexpectedly fail to configure or respond to a new device. You can refer to this maintained list of iOS Device Model #'s to update your app at strategic times.

iOS includes device-independent interfaces to detect hardware capabilities and parameters such as screen size. The generalized interfaces Apple provides are usually the safest, best supported mechanisms to dynamically adapt an app's behavior to different hardware. Nevertheless, the following code can be useful for prototyping, debugging, testing, or any time code needs to target a specific device family. This technique can also be useful to describe the current device by its common/publicly recognized name.

Swift 3

// 1. Declare outside class definition (or in its own file).
// 2. UIKit must be included in file where this code is added.
// 3. Extends UIDevice class, thus is available anywhere in app.
//
// Usage example:
//
//    if UIDevice().type == .simulator {
//       print("You're running on the simulator... boring!")
//    } else {
//       print("Wow! Running on a \(UIDevice().type.rawValue)")
//    }
import UIKit

public enum Model : String {
    case simulator   = "simulator/sandbox",
    iPod1            = "iPod 1",
    iPod2            = "iPod 2",
    iPod3            = "iPod 3",
    iPod4            = "iPod 4",
    iPod5            = "iPod 5",
    iPad2            = "iPad 2",
    iPad3            = "iPad 3",
    iPad4            = "iPad 4",
    iPhone4          = "iPhone 4",
    iPhone4S         = "iPhone 4S",
    iPhone5          = "iPhone 5",
    iPhone5S         = "iPhone 5S",
    iPhone5C         = "iPhone 5C",
    iPadMini1        = "iPad Mini 1",
    iPadMini2        = "iPad Mini 2",
    iPadMini3        = "iPad Mini 3",
    iPadAir1         = "iPad Air 1",
    iPadAir2         = "iPad Air 2",
    iPadPro9_7       = "iPad Pro 9.7\"",
    iPadPro9_7_cell  = "iPad Pro 9.7\" cellular",
    iPadPro10_5      = "iPad Pro 10.5\"",
    iPadPro10_5_cell = "iPad Pro 10.5\" cellular",
    iPadPro12_9      = "iPad Pro 12.9\"",
    iPadPro12_9_cell = "iPad Pro 12.9\" cellular",
    iPhone6          = "iPhone 6",
    iPhone6plus      = "iPhone 6 Plus",
    iPhone6S         = "iPhone 6S",
    iPhone6Splus     = "iPhone 6S Plus",
    iPhoneSE         = "iPhone SE",
    iPhone7          = "iPhone 7",
    iPhone7plus      = "iPhone 7 Plus",
    iPhone8          = "iPhone 8",
    iPhone8plus      = "iPhone 8 Plus",
    iPhoneX          = "iPhone X",
    iPhoneXS         = "iPhone XS",
    iPhoneXSmax      = "iPhone XS Max",
    iPhoneXR         = "iPhone XR",
    iPhone11         = "iPhone 11",
    iPhone11Pro      = "iPhone 11 Pro",
    iPhone11ProMax   = "iPhone 11 Pro Max",
    unrecognized     = "?unrecognized?"
}

public extension UIDevice {
    public var type: Model {
        var systemInfo = utsname()
        uname(&systemInfo)
        let modelCode = withUnsafePointer(to: &systemInfo.machine) {
            $0.withMemoryRebound(to: CChar.self, capacity: 1) {
                ptr in String.init(validatingUTF8: ptr)

            }
        }
        var modelMap : [ String : Model ] = [
            "i386"       : .simulator,
            "x86_64"     : .simulator,
            "iPod1,1"    : .iPod1,
            "iPod2,1"    : .iPod2,
            "iPod3,1"    : .iPod3,
            "iPod4,1"    : .iPod4,
            "iPod5,1"    : .iPod5,
            "iPad2,1"    : .iPad2,
            "iPad2,2"    : .iPad2,
            "iPad2,3"    : .iPad2,
            "iPad2,4"    : .iPad2,
            "iPad2,5"    : .iPadMini1,
            "iPad2,6"    : .iPadMini1,
            "iPad2,7"    : .iPadMini1,
            "iPhone3,1"  : .iPhone4,
            "iPhone3,2"  : .iPhone4,
            "iPhone3,3"  : .iPhone4,
            "iPhone4,1"  : .iPhone4S,
            "iPhone5,1"  : .iPhone5,
            "iPhone5,2"  : .iPhone5,
            "iPhone5,3"  : .iPhone5C,
            "iPhone5,4"  : .iPhone5C,
            "iPad3,1"    : .iPad3,
            "iPad3,2"    : .iPad3,
            "iPad3,3"    : .iPad3,
            "iPad3,4"    : .iPad4,
            "iPad3,5"    : .iPad4,
            "iPad3,6"    : .iPad4,
            "iPhone6,1"  : .iPhone5S,
            "iPhone6,2"  : .iPhone5S,
            "iPad4,1"    : .iPadAir1,
            "iPad4,2"    : .iPadAir2,
            "iPad4,4"    : .iPadMini2,
            "iPad4,5"    : .iPadMini2,
            "iPad4,6"    : .iPadMini2,
            "iPad4,7"    : .iPadMini3,
            "iPad4,8"    : .iPadMini3,
            "iPad4,9"    : .iPadMini3,
            "iPad6,3"    : .iPadPro9_7,
            "iPad6,11"   : .iPadPro9_7,
            "iPad6,4"    : .iPadPro9_7_cell,
            "iPad6,12"   : .iPadPro9_7_cell,
            "iPad6,7"    : .iPadPro12_9,
            "iPad6,8"    : .iPadPro12_9_cell,
            "iPad7,3"    : .iPadPro10_5,
            "iPad7,4"    : .iPadPro10_5_cell,
            "iPhone7,1"  : .iPhone6plus,
            "iPhone7,2"  : .iPhone6,
            "iPhone8,1"  : .iPhone6S,
            "iPhone8,2"  : .iPhone6Splus,
            "iPhone8,4"  : .iPhoneSE,
            "iPhone9,1"  : .iPhone7,
            "iPhone9,2"  : .iPhone7plus,
            "iPhone9,3"  : .iPhone7,
            "iPhone9,4"  : .iPhone7plus,
            "iPhone10,1" : .iPhone8,
            "iPhone10,2" : .iPhone8plus,
            "iPhone10,3" : .iPhoneX,
            "iPhone10,6" : .iPhoneX,
            "iPhone11,2" : .iPhoneXS,
            "iPhone11,4" : .iPhoneXSmax,
            "iPhone11,6" : .iPhoneXSmax,
            "iPhone11,8" : .iPhoneXR,
            "iPhone12,1" : .iPhone11,
            "iPhone12,3" : .iPhone11Pro,
            "iPhone12,5" : .iPhone11ProMax
        ]

    if let model = modelMap[String.init(validatingUTF8: modelCode!)!] {
            return model
        }
        return Model.unrecognized
    }
}

Solution 4

Yet another/simple alternative (model identifier reference found at https://www.theiphonewiki.com/wiki/Models):

Updated answer for Swift 3/4/5 including string trimming and simulator support:

func modelIdentifier() -> String {
    if let simulatorModelIdentifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] { return simulatorModelIdentifier }
    var sysinfo = utsname()
    uname(&sysinfo) // ignore return value
    return String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters)
}

Solution 5

I've made another sample extension on UIDevice to include simulator model identifier base on @HAS's answer . It's working fine with Swift3.2 above(include Swift 4.x, Swift 5):

let modelName = UIDevice.current.modelName

New add Models: iPod touch (7th generation), iPhone SE (2nd generation), iPhone 12 mini, iPhone 12, iPhone 12 Pro, iPhone 12 Pro Max, iPad Pro (12.9-inch) (4th generation)

import UIKit

public extension UIDevice {

    /// pares the deveice name as the standard name
    var modelName: String {

        #if targetEnvironment(simulator)
            let identifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"]!
        #else
            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)))
            }
        #endif

        switch identifier {
        case "iPod5,1":                                 return "iPod Touch 5"
        case "iPod7,1":                                 return "iPod Touch 6"
        case "iPod9,1":                                 return "iPod touch (7th generation)"
        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 "iPhone12,1":                              return "iPhone 11"
        case "iPhone12,3":                              return "iPhone 11 Pro"
        case "iPhone12,5":                              return "iPhone 11 Pro Max"
        case "iPhone12,8":                              return "iPhone SE (2nd generation)"
        case "iPhone13,1":                              return "iPhone 12 mini"
        case "iPhone13,2":                              return "iPhone 12"
        case "iPhone13,3":                              return "iPhone 12 Pro"
        case "iPhone13,4":                              return "iPhone 12 Pro Max"
        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) (2nd generation)"
        case "iPad7,3", "iPad7,4":                      return "iPad Pro (10.5-inch)"
        case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return "iPad Pro (11-inch)"
        case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return "iPad Pro (12.9-inch) (3rd generation)"
        case "iPad8,11", "iPad8,12":                    return "iPad Pro (12.9-inch) (4th generation)"
        case "AppleTV5,3":                              return "Apple TV"
        case "AppleTV6,2":                              return "Apple TV 4K"
        case "AudioAccessory1,1":                       return "HomePod"
        default:                                        return identifier
        }
    }
}
Share:
333,425
The Mach System
Author by

The Mach System

Who am I: Alvis Mach - a passionate programmer. What I do: I'm currently working as an iOS application developer at Commonwealth Bank in Sydney, Australia..

Updated on July 08, 2022

Comments

  • The Mach System
    The Mach System almost 2 years

    Is there a way to get the device model name (iPhone 4S, iPhone 5, iPhone 5S, etc) in Swift?

    I know there is a property named UIDevice.currentDevice().model but it only returns device type (iPod touch, iPhone, iPad, iPhone Simulator, etc).

    I also know it can be done easily in Objective-C with this method:

    #import <sys/utsname.h>
    
    struct utsname systemInfo;
    uname(&systemInfo);
    
    NSString* deviceModel = [NSString stringWithCString:systemInfo.machine
                              encoding:NSUTF8StringEncoding];
    

    But I'm developing my iPhone app in Swift so could someone please help me with the equivalent way to solve this in Swift?

  • The Mach System
    The Mach System over 9 years
    Thanks mstysf. But I think I have found a solution in here <stackoverflow.com/a/25380129>. However, do you you know whether it is possible to tell between iPhone Simulators (iPhone4s,iPhone5,iPhone6)? Because it seems to me that it only returns "x86_64" for all iPhone Simulators no matter what model I have chosen.
  • The Mach System
    The Mach System over 9 years
    Sorry I think an error occurred while coping. Here is the link : stackoverflow.com/a/25380129/2640210
  • clearlight
    clearlight over 9 years
    I think this is great (advanced Swift), and I'm trying to figure it out to see what other optimizations I can do to it. One thing is that older devices don't support the later versions of iOS that has Swift support so it seems pointless to list information about anything preceding the iPhone 4S and the iPad 2 for iOS 8+ for a Swift only example :-)
  • HAS
    HAS over 9 years
    Haha you are absolutely right (except that it's not iOS 8+ but 7+). Thanks for the comment and the feedback! Feel free to edit my answer, otherwise I'll do it when I'm back from holidays :)
  • clearlight
    clearlight over 9 years
    I revamped your example and posted a new one below. All the heavy lifting was done by you and others. I just experimented and combined and refined.
  • Dan Beaulieu
    Dan Beaulieu almost 9 years
    @HAS reflect is throwing an error in iOS 9, did they deprecate it?
  • HAS
    HAS almost 9 years
    @DanBeaulieu Thanks for reporting! There was actually a known bug when creating large tuples (the Swift runtime metadata cache crashed). However, this has been fixed in Xcode 7 Beta 4. From the release notes: The Swift runtime metadata cache crash when trying to form very large tuple types has been fixed. (21659505). I've updated my answer to reflect the changes they made in this beta (the Mirror API has completely changed [to the better IMO])! :)
  • DrPatience
    DrPatience over 8 years
    On Swift 2 replace: let machinePtr = advance(ptr.baseAddress, Int(_SYS_NAMELEN * 4)) with let machinePtr = ptr.baseAddress.advancedBy(Int(_SYS_NAMELEN * 4))
  • Doug Richardson
    Doug Richardson over 8 years
    @HAS how did you determine the mapping from uname output to iPhone marketing names?
  • HAS
    HAS over 8 years
    @Doug Good question, I should've probably included that in the answer ... theiphonewiki.com/wiki/Models
  • clearlight
    clearlight over 8 years
    @TheMachSystem That's the whole problem with this approach. It isn't the right way to adapt your app's behavior in most cases. You should be sniffing out the hardware configuration and characteristics using more generalized standard iOS interfaces wherever possible although that might require some more research and coding effort.
  • alekperos
    alekperos over 8 years
    you do have duplicate keys in modelMap that makes iOS to complain: Duplicate literals in keys
  • Deepak Thakur
    Deepak Thakur about 8 years
    XCode 7.2 says that line if let dir = NSProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] will never be executed.
  • Nazik
    Nazik about 8 years
    @DeepakThakur, did u try running in simulator? me too using Xcode 7.2, it's working fine
  • Sti
    Sti about 8 years
    If you now update to Xcode 7.3 and have support for iOS7, this code will crash for iPhone 4-users(exclusively)! Seems like an Apple-bug, since it still compiles without error..
  • HAS
    HAS about 8 years
    @Sti Thanks for reporting! I'm unfortunately unable to reproduce this since I don't own an iPhone 4. Can you, by any chance, tell if other Swift 2 code is also affected? (My best guess: Apple modified the Objc runtime to support Swift, maybe the new Swift 2 reflection features are not supported in the old version of that runtime?)
  • Sti
    Sti about 8 years
    @HAS When changing this code to something else, my entire app runs fine (as far as I can tell, not completely tested all functions). It was the Mirror(...) line that crashed. I do not know of any other cases yet, but I have sent a bug report. I might perform a complete test on iPhone 4 later, and will report back.
  • HAS
    HAS about 8 years
    Thanks @Sti! That seems to confirm my suspicion. Thank you for taking care!
  • Jayprakash Dubey
    Jayprakash Dubey almost 8 years
    iPhone 6 and iPhone 6 plus size are different. How to handle this?
  • Nazik
    Nazik almost 8 years
    @JayprakashDubey, in that method it'll return "iPhone 6 Plus" for 6 plus, u can check...
  • xoudini
    xoudini over 7 years
    @TheMachSystem Chiming in a bit late perhaps, but the answer to your question (if it's possible to differentiate between iDevice models in the Simulator) is no. The reason you're getting x86_64 from utsname is that the Simulator is actually your computer which has the machine property x86_64. Try by changing .machine to .nodename in your method the return value will be something like My-iMac.local.
  • William T.
    William T. over 7 years
    Result I get back is just "iPhone", when I run on any of the simulators.
  • A.J. Hernandez
    A.J. Hernandez over 7 years
    the cocoa pods is awesome. just what i needed!
  • HAS
    HAS over 7 years
    Thanks @A.J. Hernandez ☺️
  • hfossli
    hfossli over 7 years
    It's not "pure swift" if it depends on any iOS/OSX specific frameworks. See github.com/colemancda/PureSwiftList
  • alekperos
    alekperos over 7 years
    The latest Swift 3.0.2 complains about the part if let model = modelMap[String.fromCString(modelCode!)!]. Workaround can be decoding CString first and then feeding decoded string to modelMap ` if let (str, _) = String.decodeCString(modelCode, as: UTF8.self, repairingInvalidCodeUnits: false) { if let model = modelMap[str] { return model } } `
  • wuf810
    wuf810 over 7 years
    As @alekperos says there is a typo in the code. It should be : if let model = modelMap[String.init(validatingUTF8: deviceModelCode()!)!] { return model }
  • Admin
    Admin over 7 years
    This solution returns just model as "iPhone" or "iPod touch". Not the particular device like "iPhone 6s"
  • HAS
    HAS over 7 years
    @hfossli I know, that's why I put it in quotation marks, it was basically saying (at the time it was an answer to Kevin's comment) that this is not an answer that implements the functionality in Objc and import it via a bridging header.
  • J. Chomel
    J. Chomel about 7 years
    While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
  • Pokemon
    Pokemon about 7 years
    Dose someone know What string will be returned as modelCode! if user using iPhoneSE ?
  • Pokemon
    Pokemon about 7 years
    Thanks, updating for recent device is always helpful.
  • jk7
    jk7 about 7 years
    And the Objective-C equivalent to get the simulator type is: [NSProcessInfo processInfo].environment[@"SIMULATOR_MODEL_IDENTIFIER"]
  • Voyteck
    Voyteck about 7 years
    Is there a possibility to detect a device color in Swift too?
  • HAS
    HAS about 7 years
    @Voyteck I haven't tested this answer yet, maybe it still works, however note that it is private API and you probably won't get your app in the AppStore with that code.
  • Voyteck
    Voyteck about 7 years
    UIDevice.current seems to be an official API, but I can not find an information on device color there. Unless UIDevice.current.identifierForVendor (i.e. UUID) has it encoded?
  • HAS
    HAS about 7 years
    Did you look at the linked answer? You have to perform a selector on UIDevice.current which gives you back the color (you can't just call a function since it's not public API).
  • ItsMeAgain
    ItsMeAgain about 7 years
    @clearlight which dimension category represents the iPad Pro?
  • ItsMeAgain
    ItsMeAgain about 7 years
    @clearlight I am using your updated code and testing on iPad Pro (9.7 inch) - iOS 10.2 (14C89) Simulator but it is categorized as unrecognized. What could be the reason? I thought it should be recognized as simulator.
  • NiñoScript
    NiñoScript over 6 years
    Pro tip: this can be changed to a static let so it will be lazily evaluated only once!
  • Sazzad Hissain Khan
    Sazzad Hissain Khan about 6 years
    great. simplest answer
  • Aleem
    Aleem about 6 years
    Check this github.com/aleemrazzaq/ARCompactDeviceInfo this has latest Device model, iPhone X, iPhone 8, 8 Plus and iPad 6th Generation 2018
  • Radu Ursache
    Radu Ursache about 6 years
    your output is wrong, you have to ask for the UIDevice().type.rawvalue to get the device name with spaces.
  • gone
    gone almost 6 years
    Unfortunately, simulated devices all return as "Simulator". Is it possible to identify the model being simulated?
  • HAS
    HAS almost 6 years
    @gone Yeah it’s possible, if you use my linked DeviceKit library you get it out of the box, when I’m home (I’m still only mobile) I’ll update this answer to include that code, good point, I thought it already did!
  • HAS
    HAS almost 6 years
    @gone I've adapted the answer to also support simulators :) HTH
  • Jordan H
    Jordan H over 5 years
    Could you update this for iPhone XS, XS Max, and XR please :)
  • HAS
    HAS over 5 years
    What do you mean? Isn’t it “iPhone Xs”?
  • Jordan H
    Jordan H over 5 years
    Thanks @HAS! I updated them per official Apple formatting (macrumors.com/2018/09/18/…)
  • HAS
    HAS over 5 years
    @Joey :O Thanks for linking to the post and correcting the answer, I didn't know that! Great!
  • Pedro Paulo Amorim
    Pedro Paulo Amorim over 5 years
    Where is the configuration for iPhone Xs, Max and Xr?
  • Rick
    Rick over 5 years
    This doesn't seem to work in Xcode 10/Mojave. I just get "x86_64" when run in the simulator.
  • Jordan H
    Jordan H over 5 years
    Hi @HAS I'm back to request the addition of the third gen iPad Pros 😅
  • HAS
    HAS over 5 years
    @Joey Done :):)
  • Dani
    Dani over 5 years
    Can I submit this to Apple? Or will it get rejected?
  • Dani
    Dani over 5 years
    @Rick what device?
  • HAS
    HAS over 5 years
    @dani-springer This is public API so it won’t get rejected :)
  • Dani
    Dani over 5 years
    @HAS awesome. If we were to take away the whole extension, what is the actual property from which we are getting this info? (I guess "iPhone 9,3") I couldn't find it going through the properties of UIDevice.
  • HAS
    HAS over 5 years
    There is no such property, hence the extension :) The value that identifies the device at runtime is part of what utsname() returns (e.g. “iPhone9,3”), this is then mapped (with the help of theiphonewiki.com/wiki/Models) to the correct string (“iPhone 7”) (as in this answer) or the correct model (.iPhone7) (as in the linked DeviceKit framework).
  • Jordan H
    Jordan H about 5 years
    Hi @HAS it's me again 😏 here to request the addition of the new iPad Air and iPad mini
  • HAS
    HAS about 5 years
    Hey Jordan, the site I usually get the identifiers from still lists them as “Unknown”. I’ll update the answer as soon as they are known. :)
  • DJFriar
    DJFriar about 5 years
    I'm not getting the formatted version with spaces using UIDevice().type, and if I add .rawvalue to the end of that, I get an error stating: Value of type 'Model' has no member 'rawvalue'
  • Alessandro Ornano
    Alessandro Ornano about 5 years
    @DJFriar About the rawvalue , this one is not longer necessary with Swift 5, I've update that line. I've tested now the code and it works correctly, what kind of device are you try to test? Have you other UIDevice extensions in your prj?
  • DJFriar
    DJFriar about 5 years
    @AlessandroOrnano I'm testing on an iPhone 6s and an iPhone XS Max. Both printing to console and using as a variable return it without spaces. All software is latest public release. No other UIDevice extensions aside from yours (housed in a dedicated swift file).
  • DJFriar
    DJFriar about 5 years
    @AlessandroOrnano Did you see my above comment?
  • Alessandro Ornano
    Alessandro Ornano about 5 years
    @DJFriar Sure but I dont understand what is your output
  • Julius
    Julius almost 5 years
    I would not recommend using private APIs
  • DawnSong
    DawnSong almost 5 years
    @Julius You are right. It always works, and don't need to update your code with new Apple devices release.
  • bshirley
    bshirley almost 5 years
    this one has the added bonus of being non-UIKit dependent
  • bshirley
    bshirley almost 5 years
    this one has the added bonus of being non-UIKit dependent
  • Burak Dizlek
    Burak Dizlek over 4 years
    Are you sure @Wolverian ? I am using already like that in my project.
  • Burak Dizlek
    Burak Dizlek over 4 years
    Yes you are right. I forgot I used a library for this. It is ok now.
  • Laura Calinoiu
    Laura Calinoiu over 4 years
    Could you update this for the new iPhones? iPhone 11, iPhone 11 Pro, iPhone 11 Pro Max. Thank you
  • Jafar Khoshtabiat
    Jafar Khoshtabiat over 4 years
    is this public api or private? I mean can I use it in my application that I want to put in App Store?
  • Jens Schwarzer
    Jens Schwarzer over 4 years
    Hi @JafarKhoshtabiat :) It is part of UNIX and I have used it in apps on App Store for many years :)
  • gutte
    gutte over 4 years
    For simulator detection use: #if targetEnvironment(simulator) #endif
  • Houman
    Houman over 4 years
    A shame, this solution looks great. But I can't get it to work on Swift 5. Any advice?
  • Houman
    Houman over 4 years
    That's the best answer if you need it to work across macos and ios.
  • Jordan H
    Jordan H about 4 years
    Note that this does not return iPhone 6s for example, it returns iPhone8,1.
  • Hitit
    Hitit about 4 years
    in order to get the model name with spaces correctly, one must call UIDevice().type.rawValue. Or else you need to change type:Model to type:String and change return values to 'simModel.rawValue', 'model.rawValue', 'Model.unrecognized.rawValue'
  • idej1234
    idej1234 about 4 years
    Returns iPhone7 for an iPhone6 so advise against using this.
  • Houman
    Houman about 4 years
    Btw the iPhone 11 simulator returns Phone12,1, what gives? And the simulator detection isn't working at all.
  • Jens Schwarzer
    Jens Schwarzer about 4 years
    @Houman not sure what you mean? The code returns "12,1" for both iPhone 11 simulator and real iPhone 11, which is the whole idea! If you leave out the line with if let... then you will not get "12,1" when running in simulator :)
  • rusBogun
    rusBogun about 4 years
    what about iPhoneSE2? Thnx
  • tperei
    tperei about 4 years
    Please add iPhone SE 2nd Gerenation. iPhone12,8
  • Luke
    Luke about 4 years
    @Houman Identifer is different than the device model. So it is expected to get "12,1" as the output. Check the link in the answer.
  • pushpank
    pushpank almost 4 years
    let deviceName = device.name print(deviceName). getting Ambiguous use of 'name' error
  • Danny Law
    Danny Law almost 4 years
    May seem obvious but you need to "import UIKit" I also had to do "UIDevice().type.rawValue" to format as "iPhone 11 Pro".
  • cherryblossom
    cherryblossom almost 4 years
    An older revision of this is used in Australia's CovidSafe app copied exactly, even the swiftlint:disable:this despite the project not even using SwiftLint. For some reason, I find it a bit funny that a government app uses copied and pasted Stack Overflow code (even though the majority of apps probably already do that).
  • Frederic Adda
    Frederic Adda almost 4 years
    This solution is not sustainable: you would have to create a new release of your app each time there is a new model.
  • Frederic Adda
    Frederic Adda almost 4 years
    This solution is not sustainable: you would have to create a new release of your app each time there is a new model.
  • Alessandro Ornano
    Alessandro Ornano almost 4 years
    @FrédéricAdda An update of your app one time in a year should be normal. The other real solution don't give you output like this kind of code.
  • Frederic Adda
    Frederic Adda almost 4 years
    @AlessandroOrnano I think it would be more than once a year, basically each time Apple releases a new product. I found a more reliable solution based on utsname.
  • Alessandro Ornano
    Alessandro Ornano almost 4 years
    @FrédéricAdda If you pay attention to my code, I use utsname: my code is an extension of the normal utsname info. IMHO you shouldn't base your app to utsname infos, these are verbose debug informations.
  • Vladimir Kuzomenskyi
    Vladimir Kuzomenskyi over 3 years
    Does not work for me on iOS 12.4 simulator but does work for iOS 13.5 device
  • Alessandro Ornano
    Alessandro Ornano over 3 years
    @VladimirKuzomenskyi Tested now with iOS 12.4 and iPhone SE 1gen simulator: it works. Could you specify the simulator model used?
  • Vladimir Kuzomenskyi
    Vladimir Kuzomenskyi over 3 years
    @AlessandroOrnano Yes, I did tested again, the extension does actually work for the simulator! I've just forgot to reinstall my app completely so I didn't see my code working. Sorry for that, your code works! =)
  • Hattori Hanzō
    Hattori Hanzō over 3 years
    recommended library
  • Jordan H
    Jordan H over 3 years
    I’m baaaaack 😈 can we get iPad Air (4th generation, iPhone 12, iPhone 12 mini, iPhone 12 Pro, and iPhone 12 Pro Max :)
  • Boobesh Suresh Appu
    Boobesh Suresh Appu over 3 years
    Can we follow same format for iPad Mini Strings... We're using "iPad mini (5th generation)" for latest version why don't we have older versions of iPad mini like "iPad mini (1st generation)", "iPad mini (2nd generation)" like these?
  • Lorenzo
    Lorenzo over 3 years
    The "type" is not available anymore. Use UIDevice().name instead
  • Alessandro Ornano
    Alessandro Ornano over 3 years
    @Lorenzo According with the latest Xcode 12.2 with swift 5.3.1, there is no conflicts with UIDevice().type, remember that my extension creates the variable type to obtain all the correct informations.
  • yoAlex5
    yoAlex5 over 3 years
    Family(iPhone7) has Id(iPhone9,1, iPhone9,3) which has Model: 9,1 - A1660, A1779, A1780 and 9,3 - A1778. Find it here: everymac.com/ultimate-mac-lookup/…
  • eli7ah
    eli7ah over 3 years
    super accurate, thanx to Alessandro Ornano and everybody who participated in! also got a link for this )
  • juanjovn
    juanjovn over 3 years
    It does not work in Apple Silicon (M1 Mac Mini). It always returns Model.unrecognized in simulators. Although in real devices works as expected (tested in iPhone X and 12 mini). EDIT: Fixed adding "arm64" : .simulator, to the dictionary
  • David H
    David H over 3 years
    People missing the point: Apple doesn't give you "iPhone 12 Max", it gives you these command separated strings, you need to then map them to their "plain text" model names! He even cals this out in the code block header!!!
  • Greg
    Greg about 3 years
    This only works sometimes for me (M1 MacBook Pro). It appears to work on simulators with iOS 13.7 and below, but not on any with iOS 14+.
  • Alexander Volkov
    Alexander Volkov about 3 years
    iPod mapping is incorrect. I skipped to check the rest.
  • Alessandro Ornano
    Alessandro Ornano about 3 years
    @AlexanderVolkov Pay attention: there are seven gen of iPods: "iPod1,1" : .iPod1, "iPod2,1" : .iPod2, "iPod3,1" : .iPod3, "iPod4,1" : .iPod4, "iPod5,1" : .iPod5, "iPod7,1" : .iPod6, "iPod9,1" : .iPod7, where is the mistake? You can check also here theiphonewiki.com/wiki/Models
  • Alexander Volkov
    Alexander Volkov about 3 years
    @AlessandroOrnano Sorry connected wrong answer =).
  • Alexander Volkov
    Alexander Volkov about 3 years
    iPod mapping is incorrect. I skipped to check the rest.
  • Ky -
    Ky - almost 3 years
    > ignore return value - The return value for that function is an error code. Best to not ignore errors.
  • Jens Schwarzer
    Jens Schwarzer almost 3 years
    @KyLeggiero please check the documentation for uname. As you can see it will only fail if you don’t provide a proper structure. But I do that and so it is irrelevant. This is the reason for my comment so the reader can see that I have taken an active decision not to check the return value. But feel free to add this in your own version if you are worried 🤓
  • Ky -
    Ky - almost 3 years
    @JensSchwarzer My system's documentation for uname and the official UNIX specification both say that uname returns a non-zero integer when an error occurred, without specifying a scope for the error: i.imgur.com/SODOhiJ.png - pubs.opengroup.org/onlinepubs/9699919799/utilities/uname.htm‌​l
  • Jens Schwarzer
    Jens Schwarzer almost 3 years
    @KyLeggiero Yikes! Well, I am pretty sure it never failed. But feel free to add a test in your own code if this keeps you awake at night ;)
  • Jens Schwarzer
    Jens Schwarzer over 2 years
    @Aura this is correct. Please check the webpage in the beginning for look-up for a specific version :)
  • mklbtz
    mklbtz over 2 years
    This answer is underrated! So much simpler than using a Mirror. You can even simplify this further by omitting the withUnsafePointer call like this: return String(cString: &sysinfo.machine.0)
  • Stunner
    Stunner over 2 years
    @mklbtz Good tip, only issue with that is that it returns an optional String. I expect the return value of something like deviceName() to be a non-optional or I'd be using your suggestion.
  • Mehul
    Mehul over 2 years
    This is just updated with all new iOS devices, This is best answer from all above.
  • Mehul
    Mehul over 2 years
    Thank you @AlessandroOrnano for the updates..
  • Alessandro Ornano
    Alessandro Ornano over 2 years
    If any of you have the time and desire, try the experiment here just to find out if there are any errors thank you
  • mklbtz
    mklbtz over 2 years
    @Stunner mm, maybe you misunderstood me but no this doesn't make it optional. ``` func deviceName() -> String { var systemInfo = utsname() uname(&systemInfo) return String(cString: &systemInfo.machine.0) } ```
  • CyberMew
    CyberMew over 2 years
    @AlexanderVolkov which one is incorrect and what should it be? Let’s improve it together rather than just saying it’s wrong. If you know, do share with us!
  • bauerMusic
    bauerMusic over 2 years
    As mentioned before, the problem with all of the answers is that the 'static' list of devices needs to be constantly updated. Is there a repos somewhere with updated devices list?
  • bauerMusic
    bauerMusic over 2 years
  • Patrick
    Patrick over 2 years
    DeviceGuru doesn't seem to have been updated in a while. I wrote a similar package that checks for new updates every day automatically. github.com/ptrkstr/Devices
  • Patrick
    Patrick over 2 years
    This is an awesome solution! The only obvious limitation is that it requires a network. I wrote an auto updating Swift package that works offline: github.com/ptrkstr/Devices
  • Patrick
    Patrick over 2 years
    This is great! It inspired me to create something similar that works on all swift platforms (mac, ios, tvos, watchkit, linux) and is wrapped as a swift package. It also does a check everyday for new devices: github.com/ptrkstr/Devices
  • dieterdreist
    dieterdreist over 2 years
    The device name for arm based simulators (M1 silicon) is "arm64"