451

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?

Eric Aya
  • 68,765
  • 33
  • 165
  • 232
The Mach System
  • 5,790
  • 3
  • 12
  • 20
  • 3
    Do it in Objective C and just call that from Swift. – Kevin Jan 03 '15 at 21:26
  • Check this https://github.com/aleemrazzaq/ARCompactDeviceInfo – Aleem Apr 04 '18 at 11:16
  • Does anyone know what [CarPlay](https://www.apple.com/ios/carplay/) returns as an identifier? I'm guessing apps can be installed on it. – jww Jul 13 '18 at 23:22
  • take a look please https://stackoverflow.com/a/52821290/3472073 – ale_stro Nov 12 '18 at 13:02
  • @jww CarPlay runs on the iOS device. iOS just uses the display, touch inputs, speakers etc. from the car (stereo), everything is executed on the iOS device, not on the car (stereo). – d4Rk Nov 22 '18 at 13:55
  • The most reliable way: https://stackoverflow.com/a/56145991/1107242 – DawnSong May 16 '19 at 07:47

30 Answers30

1049

I made this "pure Swift" extension on UIDevice.

This version works in Swift 2 or higher If you use an earlier version please use an older version of my answer.

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 "iPhone8,4":                               return "iPhone SE"
            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 "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 (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 "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 "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 "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 "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 "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":                          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 9.7 Inch", for simulators it returns "Simulator " + Simulator identifier, e.g. "Simulator iPad Pro 9.7 Inch"

Harshil Patel
  • 785
  • 1
  • 3
  • 17
HAS
  • 17,072
  • 6
  • 28
  • 50
  • 2
    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 :-) – clearlight Jan 03 '15 at 17:57
  • 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 :) – HAS Jan 03 '15 at 18:22
  • 2
    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. – clearlight Jan 03 '15 at 23:41
  • 2
    @HAS reflect is throwing an error in iOS 9, did they deprecate it? – Dan Beaulieu Jul 22 '15 at 00:57
  • 1
    @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])! :) – HAS Jul 22 '15 at 08:22
  • @HAS how did you determine the mapping from uname output to iPhone marketing names? – Doug Richardson Oct 05 '15 at 17:33
  • 3
    @Doug Good question, I should've probably included that in the answer ... https://www.theiphonewiki.com/wiki/Models – HAS Oct 06 '15 at 04:24
  • 1
    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.. – Sti Apr 21 '16 at 07:34
  • @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?) – HAS Apr 22 '16 at 10:10
  • @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. – Sti Apr 22 '16 at 10:20
  • Thanks @Sti! That seems to confirm my suspicion. Thank you for taking care! – HAS Apr 22 '16 at 12:02
  • 1
    the cocoa pods is awesome. just what i needed! – A.J. Hernandez Nov 03 '16 at 19:08
  • 1
    Thanks @A.J. Hernandez ☺️ – HAS Nov 04 '16 at 06:55
  • It's not "pure swift" if it depends on any iOS/OSX specific frameworks. See https://github.com/colemancda/PureSwiftList – hfossli Nov 25 '16 at 12:44
  • @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. – HAS Feb 04 '17 at 19:19
  • Is there a possibility to detect a device **color** in Swift too? – Voyteck Mar 22 '17 at 12:00
  • @Voyteck I haven't tested [this](http://stackoverflow.com/a/19325796/1489885) 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. – HAS Mar 22 '17 at 12:03
  • 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? – Voyteck Mar 22 '17 at 12:19
  • 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). – HAS Mar 22 '17 at 12:23
  • 1
    Pro tip: this can be changed to a `static let` so it will be lazily evaluated only once! – NiñoScript Oct 06 '17 at 20:15
  • Check this https://github.com/aleemrazzaq/ARCompactDeviceInfo this has latest Device model, iPhone X, iPhone 8, 8 Plus and iPad 6th Generation 2018 – Aleem Apr 04 '18 at 11:17
  • Unfortunately, simulated devices all return as "Simulator". Is it possible to identify the model being simulated? – gone May 16 '18 at 07:57
  • 1
    @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 May 19 '18 at 11:22
  • 1
    @gone I've adapted the answer to also support simulators :) HTH – HAS May 20 '18 at 18:06
  • 4
    Could you update this for iPhone XS, XS Max, and XR please :) – Jordan H Sep 16 '18 at 17:14
  • What do you mean? Isn’t it “iPhone Xs”? – HAS Sep 19 '18 at 12:23
  • 1
    Thanks @HAS! I updated them per official Apple formatting (https://www.macrumors.com/2018/09/18/psa-its-iphone-xs-and-iphone-xr-in-all-caps/) – Jordan H Sep 21 '18 at 16:09
  • @Joey :O Thanks for linking to the post and correcting the answer, I didn't know that! Great! – HAS Sep 21 '18 at 20:07
  • This doesn't seem to work in Xcode 10/Mojave. I just get "x86_64" when run in the simulator. – Rick Oct 31 '18 at 03:43
  • 2
    Hi @HAS I'm back to request the addition of the third gen iPad Pros – Jordan H Nov 01 '18 at 04:08
  • @Joey Done :):) – HAS Nov 01 '18 at 09:35
  • 1
    Can I submit this to Apple? Or will it get rejected? – Daniel Springer Nov 30 '18 at 02:12
  • @Rick what device? – Daniel Springer Nov 30 '18 at 02:27
  • 1
    @dani-springer This is public API so it won’t get rejected :) – HAS Nov 30 '18 at 09:43
  • @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. – Daniel Springer Nov 30 '18 at 14:00
  • 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 https://www.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). – HAS Nov 30 '18 at 17:10
  • 1
    Hi @HAS it's me again here to request the addition of the new iPad Air and iPad mini – Jordan H Mar 23 '19 at 05:33
  • 1
    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. :) – HAS Mar 24 '19 at 12:12
  • 1
    Could you update this for the new iPhones? iPhone 11, iPhone 11 Pro, iPhone 11 Pro Max. Thank you – Laura Calinoiu Sep 19 '19 at 13:36
  • what about iPhoneSE2? Thnx – rusBogun Apr 22 '20 at 07:32
  • 2
    An older revision of this is [used in Australia's CovidSafe app](https://github.com/AU-COVIDSafe/mobile-ios/blob/master/CovidSafe/DeviceIdentifier.swift#L5) 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). – cherryblossom Jun 26 '20 at 06:57
  • This solution is not sustainable: you would have to create a new release of your app each time there is a new model. – Frédéric Adda Aug 04 '20 at 12:34
  • 1
    I’m baaaaack can we get iPad Air (4th generation, iPhone 12, iPhone 12 mini, iPhone 12 Pro, and iPhone 12 Pro Max :) – Jordan H Oct 14 '20 at 22:04
  • 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? – Boobesh Suresh Appu Oct 20 '20 at 07:16
  • Family(iPhone7) has Id(iPhone9,1, iPhone9,3) which has Model: 9,1 - A1660, A1779, A1780 and 9,3 - A1778. Find it here: https://everymac.com/ultimate-mac-lookup/?search_keywords=iPhone9%2C3+%7C%7C+iPhone9%2C1 – yoAlex5 Nov 17 '20 at 12:31
  • iPod mapping is incorrect. I skipped to check the rest. – Alexander Volkov May 01 '21 at 09:09
179

Swift 5.4, both device & simulator updated to 2021

with the new: enter image description here, 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)

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",
iPad5              = "iPad 5", //iPad 2017
iPad6              = "iPad 6", //iPad 2018
iPad7              = "iPad 7", //iPad 2019
iPad8              = "iPad 8", //iPad 2020

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

//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\" 3nd 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",

// 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",

//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,

        //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,

        //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,
        

        //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,
        
        // 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,

        //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
    ]

    if let model = modelMap[String.init(validatingUTF8: modelCode!)!] {
        if model == .simulator {
            if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
                if let simModel = modelMap[String.init(validatingUTF8: simModelCode)!] {
                    return simModel
                }
            }
        }
        return model
    }
    return Model.unrecognized
  }
}

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 myDefaultFontSize: CGFloat = 26.0
switch UIDevice().type {
    case .iPhoneSE, .iPhone5, .iPhone5S: print("default value")
    case .iPhone6, .iPhone7, .iPhone8, .iPhone6S, .iPhoneX: myDefaultFontSize += 4
    default: break
}

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

Alessandro Ornano
  • 31,579
  • 11
  • 90
  • 115
  • 2
    your output is wrong, you have to ask for the `UIDevice().type.rawvalue` to get the device name with spaces. – Radu Ursache Apr 22 '18 at 10:59
  • 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' – DJFriar Apr 08 '19 at 07:49
  • @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? – Alessandro Ornano Apr 08 '19 at 07:57
  • @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 Apr 08 '19 at 08:00
  • @AlessandroOrnano Did you see my above comment? – DJFriar Apr 16 '19 at 03:51
  • @DJFriar Sure but I dont understand what is your output – Alessandro Ornano Apr 16 '19 at 05:18
  • 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' – Hitit Feb 20 '20 at 07:28
  • 1
    Please add iPhone SE 2nd Gerenation. `iPhone12,8` – HeavenlyManBR Apr 22 '20 at 16:31
  • May seem obvious but you need to "import UIKit" I also had to do "UIDevice().type.rawValue" to format as "iPhone 11 Pro". – Danny Law Jun 17 '20 at 21:42
  • This solution is not sustainable: you would have to create a new release of your app each time there is a new model. – Frédéric Adda Aug 04 '20 at 12:34
  • 1
    @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. – Alessandro Ornano Aug 05 '20 at 08:43
  • @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. – Frédéric Adda Aug 05 '20 at 10:08
  • @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. – Alessandro Ornano Aug 05 '20 at 10:23
  • Does not work for me on iOS 12.4 simulator but does work for iOS 13.5 device – Vladimir Kuzomenskyi Aug 14 '20 at 15:23
  • @VladimirKuzomenskyi Tested now with iOS 12.4 and iPhone SE 1gen simulator: it works. Could you specify the simulator model used? – Alessandro Ornano Aug 14 '20 at 16:44
  • @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! =) – Vladimir Kuzomenskyi Aug 16 '20 at 11:08
  • The "type" is not available anymore. Use UIDevice().name instead – Lorenzo Nov 14 '20 at 17:41
  • 1
    @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. – Alessandro Ornano Nov 15 '20 at 14:56
  • 1
    super accurate, thanx to **Alessandro Ornano** and everybody who participated in! also got a link for this ) – eli7ah Dec 17 '20 at 09:17
  • 1
    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 – juanjovn Jan 03 '21 at 13:54
  • 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+. – Greg Apr 19 '21 at 16:06
  • iPod mapping is incorrect. I skipped to check the rest. – Alexander Volkov May 01 '21 at 07:17
  • @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 https://www.theiphonewiki.com/wiki/Models – Alessandro Ornano May 01 '21 at 09:05
  • @AlessandroOrnano Sorry connected wrong answer =). – Alexander Volkov May 01 '21 at 09:09
163

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
    }
}
clearlight
  • 10,772
  • 11
  • 48
  • 65
  • On Swift 2 replace: let machinePtr = advance(ptr.baseAddress, Int(_SYS_NAMELEN * 4)) with let machinePtr = ptr.baseAddress.advancedBy(Int(_SYS_NAMELEN * 4)) – DrPatience Sep 18 '15 at 08:36
  • you do have duplicate keys in `modelMap` that makes iOS to complain: `Duplicate literals in keys` – alekperos Nov 08 '15 at 14:59
  • 3
    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 } } ` – alekperos Dec 22 '16 at 11:40
  • 3
    As @alekperos says there is a typo in the code. It should be : `if let model = modelMap[String.init(validatingUTF8: deviceModelCode()!)!] { return model }` – wuf810 Dec 23 '16 at 11:08
  • Dose someone know What string will be returned as modelCode! if user using iPhoneSE ? – Kang Byul Feb 22 '17 at 09:08
  • Thanks, updating for recent device is always helpful. – Kang Byul Feb 23 '17 at 02:30
  • @clearlight which dimension category represents the iPad Pro? – ItsMeAgain May 02 '17 at 18:33
  • @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. – ItsMeAgain May 03 '17 at 05:55
  • Where is the configuration for iPhone Xs, Max and Xr? – Pedro Paulo Amorim Oct 15 '18 at 17:46
121

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)
}
Jens Schwarzer
  • 2,496
  • 1
  • 20
  • 33
38

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
        }
    }
}
Raniys
  • 1,591
  • 2
  • 16
  • 30
17

For both device as well as simulators, Create a new swift file with name UIDevice.swift

Add the below code

import UIKit


public extension UIDevice {

var modelName: String {
    #if (arch(i386) || arch(x86_64)) && os(iOS)
        let DEVICE_IS_SIMULATOR = true
    #else
        let DEVICE_IS_SIMULATOR = false
    #endif

    var machineString : String = ""

    if DEVICE_IS_SIMULATOR == true
    {

        if let dir = NSProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
            machineString = dir
        }
    }
    else {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        machineString = 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 machineString {
    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 "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,7", "iPad6,8":                      return "iPad Pro"
    case "AppleTV5,3":                              return "Apple TV"
    default:                                        return machineString
    }
}
}

Then in your viewcontroller,

 let deviceType = UIDevice.currentDevice().modelName

    if deviceType.lowercaseString.rangeOfString("iphone 4") != nil {
       print("iPhone 4 or iphone 4s")
    }
    else if deviceType.lowercaseString.rangeOfString("iphone 5") != nil {
        print("iPhone 5 or iphone 5s or iphone 5c")
    }
   else if deviceType.lowercaseString.rangeOfString("iphone 6") != nil {
        print("iPhone 6 Series")
    }
Community
  • 1
  • 1
Nazik
  • 8,393
  • 26
  • 72
  • 115
16

Swift 5

/// Obtain the machine hardware platform from the `uname()` unix command
///
/// Example of return values
///  - `"iPhone8,1"` = iPhone 6s
///  - `"iPad6,7"` = iPad Pro (12.9-inch)
static var unameMachine: String {
    var utsnameInstance = utsname()
    uname(&utsnameInstance)
    let optionalString: String? = withUnsafePointer(to: &utsnameInstance.machine) {
        $0.withMemoryRebound(to: CChar.self, capacity: 1) {
            ptr in String.init(validatingUTF8: ptr)
        }
    }
    return optionalString ?? "N/A"
}
neoneye
  • 44,507
  • 23
  • 155
  • 143
  • 2
    this one has the added bonus of being non-UIKit dependent – bshirley Jun 23 '19 at 02:29
  • A shame, this solution looks great. But I can't get it to work on Swift 5. Any advice? – Houman Jan 21 '20 at 20:16
  • Note that this does not return iPhone 6s for example, it returns iPhone8,1. – Jordan H Feb 09 '20 at 00:57
  • Returns iPhone7 for an iPhone6 so advise against using this. – idej1234 Feb 25 '20 at 04:00
  • 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!!! – David H Jan 19 '21 at 17:08
13

Dealing with c structs is painful in swift. Especially if they have some kind of c arrays in it. Here is my solution: Continue to use objective-c. Just create a wrapper objective-c class that does this job and then use that class in swift. Here is a sample class that does exactly this:

@interface DeviceInfo : NSObject

+ (NSString *)model;

@end

#import "DeviceInfo.h"
#import <sys/utsname.h>

@implementation DeviceInfo

+ (NSString *)model
{
    struct utsname systemInfo;
    uname(&systemInfo);

    return [NSString stringWithCString: systemInfo.machine encoding: NSUTF8StringEncoding];
}

@end

In swift side:

let deviceModel = DeviceInfo.model()
mustafa
  • 14,396
  • 9
  • 42
  • 56
  • Thanks mstysf. But I think I have found a solution in here . 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 Sep 25 '14 at 01:56
  • Sorry I think an error occurred while coping. Here is the link : http://stackoverflow.com/a/25380129/2640210 – The Mach System Sep 25 '14 at 02:04
  • 1
    @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. – clearlight Oct 30 '15 at 14:06
  • @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`. – xoudini Aug 08 '16 at 18:15
9

I've implemented a super-lightweight library to detect the used device based on some of the given answers: https://github.com/schickling/Device.swift

It can be installed via Carthage and be used like this:

import Device

let deviceType = UIDevice.currentDevice().deviceType

switch deviceType {
case .IPhone6: print("Do stuff for iPhone6")
case .IPadMini: print("Do stuff for iPad mini")
default: print("Check other available cases of DeviceType")
}
schickling
  • 3,046
  • 4
  • 25
  • 30
9

I found that a lot all these answers use strings. I decided to change @HAS answer to use an enum:

public enum Devices: String {
    case IPodTouch5
    case IPodTouch6
    case IPhone4
    case IPhone4S
    case IPhone5
    case IPhone5C
    case IPhone5S
    case IPhone6
    case IPhone6Plus
    case IPhone6S
    case IPhone6SPlus
    case IPhone7
    case IPhone7Plus
    case IPhoneSE
    case IPad2
    case IPad3
    case IPad4
    case IPadAir
    case IPadAir2
    case IPadMini
    case IPadMini2
    case IPadMini3
    case IPadMini4
    case IPadPro
    case AppleTV
    case Simulator
    case Other
}

public extension UIDevice {

    public var modelName: Devices {
        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)))
        }

        switch identifier {
        case "iPod5,1":                                 return Devices.IPodTouch5
        case "iPod7,1":                                 return Devices.IPodTouch6
        case "iPhone3,1", "iPhone3,2", "iPhone3,3":     return Devices.IPhone4
        case "iPhone4,1":                               return Devices.IPhone4S
        case "iPhone5,1", "iPhone5,2":                  return Devices.IPhone5
        case "iPhone5,3", "iPhone5,4":                  return Devices.IPhone5C
        case "iPhone6,1", "iPhone6,2":                  return Devices.IPhone5S
        case "iPhone7,2":                               return Devices.IPhone6
        case "iPhone7,1":                               return Devices.IPhone6Plus
        case "iPhone8,1":                               return Devices.IPhone6S
        case "iPhone8,2":                               return Devices.IPhone6SPlus
        case "iPhone9,1", "iPhone9,3":                  return Devices.IPhone7
        case "iPhone9,2", "iPhone9,4":                  return Devices.IPhone7Plus
        case "iPhone8,4":                               return Devices.IPhoneSE
        case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return Devices.IPad2
        case "iPad3,1", "iPad3,2", "iPad3,3":           return Devices.IPad3
        case "iPad3,4", "iPad3,5", "iPad3,6":           return Devices.IPad4
        case "iPad4,1", "iPad4,2", "iPad4,3":           return Devices.IPadAir
        case "iPad5,3", "iPad5,4":                      return Devices.IPadAir2
        case "iPad2,5", "iPad2,6", "iPad2,7":           return Devices.IPadMini
        case "iPad4,4", "iPad4,5", "iPad4,6":           return Devices.IPadMini2
        case "iPad4,7", "iPad4,8", "iPad4,9":           return Devices.IPadMini3
        case "iPad5,1", "iPad5,2":                      return Devices.IPadMini4
        case "iPad6,3", "iPad6,4", "iPad6,7", "iPad6,8":return Devices.IPadPro
        case "AppleTV5,3":                              return Devices.AppleTV
        case "i386", "x86_64":                          return Devices.Simulator
        default:                                        return Devices.Other
        }
    }

}
Caleb Kleveter
  • 10,260
  • 8
  • 56
  • 79
8

Using Swift 3 (Xcode 8.3)

 func deviceName() -> String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let str = withUnsafePointer(to: &systemInfo.machine.0) { ptr in
            return String(cString: ptr)
        }
        return str
    }

Note: According to official dev forum answer, it is safe to use tuples in this way. Memory alignment for the big Int8 tuple will be the same as if it were a big Int8 array. ie: contiguous and not-padded.

isoiphone
  • 212
  • 2
  • 8
6

There are some problems with the accepted answer when you're using Swift 3! This answer (inspired from NAZIK) works with Swift 3 and the new iPhone models:

import UIKit


public extension UIDevice {
var modelName: String {
    #if (arch(i386) || arch(x86_64)) && os(iOS)
        let DEVICE_IS_SIMULATOR = true
    #else
        let DEVICE_IS_SIMULATOR = false
    #endif

    var machineString = String()

    if DEVICE_IS_SIMULATOR == true
    {
        if let dir = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
            machineString = dir
        }
    }
    else {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        machineString = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8 , value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
    }
    switch machineString {
    case "iPod4,1":                                 return "iPod Touch 4G"
    case "iPod5,1":                                 return "iPod Touch 5G"
    case "iPod7,1":                                 return "iPod Touch 6G"
    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 "iPhone8,4":                               return "iPhone SE"
    case "iPhone9,1", "iPhone9,3":                  return "iPhone 7"
    case "iPhone9,2", "iPhone 9,4":                 return "iPhone 7 Plus"
    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":                      return "iPad Pro (9.7 inch)"
    case "iPad6,7", "iPad6,8":                      return "iPad Pro (12.9 inch)"
    case "AppleTV5,3":                              return "Apple TV"
    default:                                        return machineString
    }
}
}
Max
  • 109
  • 1
  • 4
6

Swift 3.0 or higher

import UIKit

class ViewController: UIViewController {

    let device = UIDevice.current

    override func viewDidLoad() {
        super.viewDidLoad()

        let model = device.model
        print(model) // e.g. "iPhone"

        let modelName = device.modelName
        print(modelName) // e.g. "iPhone 6"  /* see the extension */

        let deviceName = device.name
        print(deviceName) // e.g. "My iPhone"

        let systemName = device.systemName
        print(systemName) // e.g. "iOS"

        let systemVersion = device.systemVersion
        print(systemVersion) // e.g. "10.3.2"

        if let identifierForVendor = device.identifierForVendor {

            print(identifierForVendor) // e.g. "E1X2XX34-5X6X-7890-123X-XXX456C78901"
        }
    }
}

and add the following extension

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, 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 "iPad6,11", "iPad6,12":                    return "iPad 5"
        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 "i386", "x86_64":                          return "Simulator"
        default:                                        return identifier
        }
    }
}
iAj
  • 3,467
  • 1
  • 28
  • 33
5

There is a helper library for this.

Swift 5

pod 'DeviceKit', '~> 2.0'

Swift 4.0 - Swift 4.2

pod 'DeviceKit', '~> 1.3'

if you just want to determine the model and make something accordingly.

You can use like that :

let isIphoneX = Device().isOneOf([.iPhoneX, .simulator(.iPhoneX)])

In a function :

func isItIPhoneX() -> Bool {
    let device = Device()
    let check = device.isOneOf([.iPhoneX, .iPhoneXr , .iPhoneXs , .iPhoneXsMax ,
                                .simulator(.iPhoneX), .simulator(.iPhoneXr) , .simulator(.iPhoneXs) , .simulator(.iPhoneXsMax) ])
    return check
}
Burak Dizlek
  • 3,217
  • 1
  • 18
  • 13
4

Here an modification without force unwrap and Swift 3.0:

import Foundation
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",
    iPhone6        = "iPhone 6",
    iPhone6plus    = "iPhone 6 Plus",
    iPhone6S       = "iPhone 6S",
    iPhone6Splus   = "iPhone 6S Plus",
    iPhoneSE       = "iPhone SE",
    iPhone7        = "iPhone 7",
    iPhone7plus    = "iPhone 7 Plus",
    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,
            "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,
            ]

        guard let safeModelCode = modelCode else {
            return Model.unrecognized
        }

        guard let modelString = String.init(validatingUTF8: safeModelCode) else {
            return Model.unrecognized
        }

        guard let model = modelMap[modelString] else {
            return Model.unrecognized
        }

        return model
    }
}
netshark1000
  • 6,563
  • 8
  • 49
  • 101
3

If you do not want to keep updating your code everytime Apple adds a new model to a device family, use the method below returning you the model code only.

func platform() -> String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let modelCode = withUnsafeMutablePointer(&systemInfo.machine) {
            ptr in String.fromCString(UnsafePointer<CChar>(ptr))
        }

        return String.fromCString(modelCode!)!
}
Burak
  • 487
  • 4
  • 21
3

You can use BDLocalizedDevicesModels framework to parse device info and get the name.

Then just call UIDevice.currentDevice.productName in your code.

2

Using a Swift 'switch-case':

func platformString() -> String {

    var devSpec: String

    switch platform() {

    case "iPhone1,2": devSpec = "iPhone 3G"
    case "iPhone2,1": devSpec = "iPhone 3GS"
    case "iPhone3,1": devSpec = "iPhone 4"
    case "iPhone3,3": devSpec = "Verizon iPhone 4"
    case "iPhone4,1": devSpec = "iPhone 4S"
    case "iPhone5,1": devSpec = "iPhone 5 (GSM)"
    case "iPhone5,2": devSpec = "iPhone 5 (GSM+CDMA)"
    case "iPhone5,3": devSpec = "iPhone 5c (GSM)"
    case "iPhone5,4": devSpec = "iPhone 5c (GSM+CDMA)"
    case "iPhone6,1": devSpec = "iPhone 5s (GSM)"
    case "iPhone6,2": devSpec = "iPhone 5s (GSM+CDMA)"
    case "iPhone7,1": devSpec = "iPhone 6 Plus"
    case "iPhone7,2": devSpec = "iPhone 6"
    case "iPod1,1": devSpec = "iPod Touch 1G"
    case "iPod2,1": devSpec = "iPod Touch 2G"
    case "iPod3,1": devSpec = "iPod Touch 3G"
    case "iPod4,1": devSpec = "iPod Touch 4G"
    case "iPod5,1": devSpec = "iPod Touch 5G"
    case "iPad1,1": devSpec = "iPad"
    case "iPad2,1": devSpec = "iPad 2 (WiFi)"
    case "iPad2,2": devSpec = "iPad 2 (GSM)"
    case "iPad2,3": devSpec = "iPad 2 (CDMA)"
    case "iPad2,4": devSpec = "iPad 2 (WiFi)"
    case "iPad2,5": devSpec = "iPad Mini (WiFi)"
    case "iPad2,6": devSpec = "iPad Mini (GSM)"
    case "iPad2,7": devSpec = "iPad Mini (GSM+CDMA)"
    case "iPad3,1": devSpec = "iPad 3 (WiFi)"
    case "iPad3,2": devSpec = "iPad 3 (GSM+CDMA)"
    case "iPad3,3": devSpec = "iPad 3 (GSM)"
    case "iPad3,4": devSpec = "iPad 4 (WiFi)"
    case "iPad3,5": devSpec = "iPad 4 (GSM)"
    case "iPad3,6": devSpec = "iPad 4 (GSM+CDMA)"
    case "iPad4,1": devSpec = "iPad Air (WiFi)"
    case "iPad4,2": devSpec = "iPad Air (Cellular)"
    case "iPad4,4": devSpec = "iPad mini 2G (WiFi)"
    case "iPad4,5": devSpec = "iPad mini 2G (Cellular)"

    case "iPad4,7": devSpec = "iPad mini 3 (WiFi)"
    case "iPad4,8": devSpec = "iPad mini 3 (Cellular)"
    case "iPad4,9": devSpec = "iPad mini 3 (China Model)"

    case "iPad5,3": devSpec = "iPad Air 2 (WiFi)"
    case "iPad5,4": devSpec = "iPad Air 2 (Cellular)"

    case "i386": devSpec = "Simulator"
    case "x86_64": devSpec = "Simulator"

    default: devSpec = "Unknown"
    }

    return devSpec
}
Alessandro Ornano
  • 31,579
  • 11
  • 90
  • 115
bauerMusic
  • 4,115
  • 4
  • 31
  • 41
2

Below is the code for getting the hardware string, but you need to compare these hardware string to know which device it is. I have created a class for that contains almost all the device strings(we're keeping string upto date with new devices). It's easy to use please check

Swift : GitHub/DeviceGuru

Objective-C : GitHub/DeviceUtil

public func hardwareString() -> String {
  var name: [Int32] = [CTL_HW, HW_MACHINE]
  var size: Int = 2
  sysctl(&name, 2, nil, &size, &name, 0)
  var hw_machine = [CChar](count: Int(size), repeatedValue: 0)
  sysctl(&name, 2, &hw_machine, &size, &name, 0)

  let hardware: String = String.fromCString(hw_machine)!
  return hardware
}
Inder Kumar Rathore
  • 37,431
  • 14
  • 121
  • 176
2

SWIFT 3.1

my two cents for simply calling utsname:

    func platform() -> String {
    var systemInfo = utsname()
    uname(&systemInfo)
    let size = Int(_SYS_NAMELEN) // is 32, but posix AND its init is 256....

    let s = withUnsafeMutablePointer(to: &systemInfo.machine) {p in

        p.withMemoryRebound(to: CChar.self, capacity: size, {p2 in
            return String(cString: p2)
        })

    }
    return s
}

as other did, but a bit cleaner about all the intricacy of C/Swift and back. ):

Returns values such as "x86_64"

Fattie
  • 30,632
  • 54
  • 336
  • 607
ingconti
  • 9,213
  • 2
  • 51
  • 39
2

My simple solution grouped by device and support new devices iPhone 8 and iPhone X in Swift 3:

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, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }

        switch identifier {
        case "iPhone3,1", "iPhone3,2", "iPhone3,3", "iPhone4,1":
            return "iPhone 4"

        case "iPhone5,1", "iPhone5,2", "iPhone5,3", "iPhone5,4", "iPhone6,1", "iPhone6,2", "iPhone8,4":
            return "iPhone 5"

        case "iPhone7,2", "iPhone8,1", "iPhone9,1", "iPhone9,3", "iPhone10,1", "iPhone10,4":
            return "iPhone 6,7,8"

        case "iPhone7,1", "iPhone8,2", "iPhone9,2", "iPhone9,4", "iPhone10,2", "iPhone10,5":
            return "iPhone Plus"

        case "iPhone10,3", "iPhone10,6":
            return "iPhone X"

        case "i386", "x86_64":
            return "Simulator"
        default:
            return identifier
        }
    }
}

And use:

switch UIDevice.current.modelName {
  case "iPhone 4":
  case "iPhone 5":
  case "iPhone 6,7,8":
  case "iPhone Plus":
  case "iPhone X":
  case "Simulator":
  default:
}
Zhanserik
  • 1,932
  • 1
  • 20
  • 38
2

Based on this answer and this answer. I've created a public gist

How it can be used

let boolean: Bool = UIDevice.isDevice(ofType: .iPhoneX)
// true or false

let specificDevice: DeviceModel.Model = UIDevice.modelType
// iPhone6s, iPhoneX, iPad etc...

let model: DeviceModel = UIDevice.model
// .simulator(let specificDevice), .real(let specificDevice),
// .unrecognizedSimulator(let string), .unrecognized(let string)

let modelName: String = UIDevice.model.name
// iPhone 6, iPhone X, etc...

This is the code inside the gist

public extension UIDevice {
    public static var modelCode: String {
        if let simulatorModelIdentifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] { return simulatorModelIdentifier }
        var systemInfo = utsname()
        uname(&systemInfo)
        return withUnsafeMutablePointer(to: &systemInfo.machine) {
            ptr in String(cString: UnsafeRawPointer(ptr).assumingMemoryBound(to: CChar.self))
        }
    }

    public static var model: DeviceModel {
        // Thanks https://stackoverflow.com/a/26962452/5928180
        var systemInfo = utsname()
        uname(&systemInfo)
        let modelCode = withUnsafeMutablePointer(to: &systemInfo.machine) {
            ptr in String(cString: UnsafeRawPointer(ptr).assumingMemoryBound(to: CChar.self))
        }

        // Thanks https://stackoverflow.com/a/33495869/5928180
        if modelCode == "i386" || modelCode == "x86_64" {
            if let simulatorModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"], let model = DeviceModel.Model(modelCode: simulatorModelCode) {
                return DeviceModel.simulator(model)
            } else if let simulatorModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
                return DeviceModel.unrecognizedSimulator(simulatorModelCode)
            } else {
                return DeviceModel.unrecognized(modelCode)
            }
        } else if let model = DeviceModel.Model(modelCode: modelCode) {
            return DeviceModel.real(model)
        } else {
            return DeviceModel.unrecognized(modelCode)
        }
    }

    public static var modelType: DeviceModel.Model? {
        return UIDevice.model.model
    }

    public static func isDevice(ofType model: DeviceModel.Model) -> Bool {
        return UIDevice.modelType == model
    }
}


public enum DeviceModel {
    case simulator(Model)
    case unrecognizedSimulator(String)
    case real(Model)
    case unrecognized(String)

    public enum Model: String {
        case iPod1            = "iPod 1"
        case iPod2            = "iPod 2"
        case iPod3            = "iPod 3"
        case iPod4            = "iPod 4"
        case iPod5            = "iPod 5"
        case iPad2            = "iPad 2"
        case iPad3            = "iPad 3"
        case iPad4            = "iPad 4"
        case iPhone4          = "iPhone 4"
        case iPhone4S         = "iPhone 4S"
        case iPhone5          = "iPhone 5"
        case iPhone5S         = "iPhone 5S"
        case iPhone5C         = "iPhone 5C"
        case iPadMini1        = "iPad Mini 1"
        case iPadMini2        = "iPad Mini 2"
        case iPadMini3        = "iPad Mini 3"
        case iPadAir1         = "iPad Air 1"
        case iPadAir2         = "iPad Air 2"
        case iPadPro9_7       = "iPad Pro 9.7\""
        case iPadPro9_7_cell  = "iPad Pro 9.7\" cellular"
        case iPadPro10_5      = "iPad Pro 10.5\""
        case iPadPro10_5_cell = "iPad Pro 10.5\" cellular"
        case iPadPro12_9      = "iPad Pro 12.9\""
        case iPadPro12_9_cell = "iPad Pro 12.9\" cellular"
        case iPhone6          = "iPhone 6"
        case iPhone6plus      = "iPhone 6 Plus"
        case iPhone6S         = "iPhone 6S"
        case iPhone6Splus     = "iPhone 6S Plus"
        case iPhoneSE         = "iPhone SE"
        case iPhone7          = "iPhone 7"
        case iPhone7plus      = "iPhone 7 Plus"
        case iPhone8          = "iPhone 8"
        case iPhone8plus      = "iPhone 8 Plus"
        case iPhoneX          = "iPhone X"

        init?(modelCode: String) {
            switch modelCode {
            case "iPod1,1":    self = .iPod1
            case "iPod2,1":    self = .iPod2
            case "iPod3,1":    self = .iPod3
            case "iPod4,1":    self = .iPod4
            case "iPod5,1":    self = .iPod5
            case "iPad2,1":    self = .iPad2
            case "iPad2,2":    self = .iPad2
            case "iPad2,3":    self = .iPad2
            case "iPad2,4":    self = .iPad2
            case "iPad2,5":    self = .iPadMini1
            case "iPad2,6":    self = .iPadMini1
            case "iPad2,7":    self = .iPadMini1
            case "iPhone3,1":  self = .iPhone4
            case "iPhone3,2":  self = .iPhone4
            case "iPhone3,3":  self = .iPhone4
            case "iPhone4,1":  self = .iPhone4S
            case "iPhone5,1":  self = .iPhone5
            case "iPhone5,2":  self = .iPhone5
            case "iPhone5,3":  self = .iPhone5C
            case "iPhone5,4":  self = .iPhone5C
            case "iPad3,1":    self = .iPad3
            case "iPad3,2":    self = .iPad3
            case "iPad3,3":    self = .iPad3
            case "iPad3,4":    self = .iPad4
            case "iPad3,5":    self = .iPad4
            case "iPad3,6":    self = .iPad4
            case "iPhone6,1":  self = .iPhone5S
            case "iPhone6,2":  self = .iPhone5S
            case "iPad4,1":    self = .iPadAir1
            case "iPad4,2":    self = .iPadAir2
            case "iPad4,4":    self = .iPadMini2
            case "iPad4,5":    self = .iPadMini2
            case "iPad4,6":    self = .iPadMini2
            case "iPad4,7":    self = .iPadMini3
            case "iPad4,8":    self = .iPadMini3
            case "iPad4,9":    self = .iPadMini3
            case "iPad6,3":    self = .iPadPro9_7
            case "iPad6,11":   self = .iPadPro9_7
            case "iPad6,4":    self = .iPadPro9_7_cell
            case "iPad6,12":   self = .iPadPro9_7_cell
            case "iPad6,7":    self = .iPadPro12_9
            case "iPad6,8":    self = .iPadPro12_9_cell
            case "iPad7,3":    self = .iPadPro10_5
            case "iPad7,4":    self = .iPadPro10_5_cell
            case "iPhone7,1":  self = .iPhone6plus
            case "iPhone7,2":  self = .iPhone6
            case "iPhone8,1":  self = .iPhone6S
            case "iPhone8,2":  self = .iPhone6Splus
            case "iPhone8,4":  self = .iPhoneSE
            case "iPhone9,1":  self = .iPhone7
            case "iPhone9,2":  self = .iPhone7plus
            case "iPhone9,3":  self = .iPhone7
            case "iPhone9,4":  self = .iPhone7plus
            case "iPhone10,1": self = .iPhone8
            case "iPhone10,2": self = .iPhone8plus
            case "iPhone10,3": self = .iPhoneX
            case "iPhone10,6": self = .iPhoneX
            default:           return nil
            }
        }
    }

    public var name: String {
        switch self {
        case .simulator(let model):         return "Simulator[\(model.rawValue)]"
        case .unrecognizedSimulator(let s): return "UnrecognizedSimulator[\(s)]"
        case .real(let model):              return model.rawValue
        case .unrecognized(let s):          return "Unrecognized[\(s)]"
        }
    }

    public var model: DeviceModel.Model? {
        switch self {
        case .simulator(let model):         return model
        case .real(let model):              return model
        case .unrecognizedSimulator(_):     return nil
        case .unrecognized(_):              return nil
        }
    }
}
Zonily Jame
  • 3,917
  • 2
  • 22
  • 43
2

Simplest way to get model name (marketing name)

Use private API -[UIDevice _deviceInfoForKey:] carefully, you won't be rejected by Apple,

// works on both simulators and real devices, iOS 8 to iOS 12
NSString *deviceModelName(void) {
    // For Simulator
    NSString *modelName = NSProcessInfo.processInfo.environment[@"SIMULATOR_DEVICE_NAME"];
    if (modelName.length > 0) {
        return modelName;
    }

    // For real devices and simulators, except simulators running on iOS 8.x
    UIDevice *device = [UIDevice currentDevice];
    NSString *selName = [NSString stringWithFormat:@"_%@ForKey:", @"deviceInfo"];
    SEL selector = NSSelectorFromString(selName);
    if ([device respondsToSelector:selector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        modelName = [device performSelector:selector withObject:@"marketing-name"];
#pragma clang diagnostic pop
    }
    return modelName;
}

How did I get the key "marketing-name"?

Running on a simulator, NSProcessInfo.processInfo.environment contains a key named "SIMULATOR_CAPABILITIES", the value of which is a plist file. Then you open the plist file, you will get the model name's key "marketing-name".

Community
  • 1
  • 1
DawnSong
  • 3,232
  • 1
  • 26
  • 35
1
extension UIDevice {

    public static let hardwareModel: String = {
        var path = [CTL_HW, HW_MACHINE]
        var n = 0
        sysctl(&path, 2, nil, &n, nil, 0)
        var a: [UInt8] = .init(repeating: 0, count: n)
        sysctl(&path, 2, &a, &n, nil, 0)
        return .init(cString: a)
    }()
}

UIDevice.hardwareModel // → iPhone9,3
Milos
  • 2,528
  • 20
  • 23
0
struct utsname systemInfo;
uname(&systemInfo);

NSString* deviceModel = [NSString stringWithCString:systemInfo.machine
                          encoding:NSUTF8StringEncoding];
J. Chomel
  • 7,605
  • 14
  • 37
  • 61
  • 4
    While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) 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. – J. Chomel Feb 13 '17 at 12:05
-1

In Swift 3 it'd be

 UIDevice.current.model
Amit Kalra
  • 3,907
  • 6
  • 25
  • 43
  • 3
    Result I get back is just "iPhone", when I run on any of the simulators. – William T. Nov 03 '16 at 02:40
  • 1
    This solution returns just model as "iPhone" or "iPod touch". Not the particular device like "iPhone 6s" –  Jan 15 '17 at 12:05
-1
struct DeviceType {
        static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && Constants.SCREEN_MAX_LENGTH < 568
        static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && Constants.SCREEN_MAX_LENGTH == 568
        static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone && Constants.SCREEN_MAX_LENGTH == 667
        static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone && Constants.SCREEN_MAX_LENGTH == 736
        static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && Constants.SCREEN_MAX_LENGTH == 1024
    }
CrazyPro007
  • 692
  • 4
  • 13
-1

All the answers are great. After getting some bits I have created THIS GIST

It contains DeviceModel which is part and of the 'Core' (No UIKit dependency) Module. It can even be used as a model.

It can be used from another 'Core' module component like that:

struct DeviceHelper {
    static var specificModelType: DeviceModel {
        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 modelType = DeviceModel(modelCode: modelCode ?? "")
        if modelType == .simulator {
            return .simulator
            // UP TO YOU
//            if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
//                return DeviceModel(modelCode: simModelCode)
//            }
        } else {
            return modelType
        }
}

Or from a 'UI' Module component like that:

extension UIDevice {
    static var specificModelType: DeviceModel {
        DeviceHelper.specificModelType
    }
}
Reimond Hill
  • 2,633
  • 21
  • 35
-2

For swift4.0 and above used below code:

let udid = UIDevice.current.identifierForVendor?.uuidString
let name = UIDevice.current.name
let version = UIDevice.current.systemVersion
let modelName = UIDevice.current.model
let osName = UIDevice.current.systemName
let localized = UIDevice.current.localizedModel

print(udid ?? "")
print(name)
print(version)
print(modelName)
print(osName)
print(localized)
Kiran Patil
  • 312
  • 4
  • 13
-2

this is (i think) the most updated answer:

let modelName = UIDevice.current.name

print(modelName)

that's it.

tal marom
  • 187
  • 1
  • 4
  • 5
    This doesn’t answer the question, as this gives the name the user typed in for their device, not the device model. – Jordan H Dec 27 '20 at 02:47