Reputation: 6973
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?
Upvotes: 561
Views: 431874
Reputation: 19873
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 "iPhone14,7": return "iPhone 14"
case "iPhone14,8": return "iPhone 14 Plus"
case "iPhone15,2": return "iPhone 14 Pro"
case "iPhone15,3": return "iPhone 14 Pro Max"
case "iPhone15,4": return "iPhone 15"
case "iPhone15,5": return "iPhone 15 Plus"
case "iPhone16,1": return "iPhone 15 Pro"
case "iPhone16,2": return "iPhone 15 Pro Max"
case "iPhone17,3": return "iPhone 16"
case "iPhone17,4": return "iPhone 16 Plus"
case "iPhone17,1": return "iPhone 16 Pro"
case "iPhone17,2": return "iPhone 16 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 "iPad13,18", "iPad13,19": return "iPad (10th 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 "iPad14,8", "iPad14,9": return "iPad Air (11-inch) (M2)"
case "iPad14,10", "iPad14,11": return "iPad Air (13-inch) (M2)"
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 "iPad16,1", "iPad16,2": return "iPad mini (A17 Pro)"
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 "iPad14,3", "iPad14,4": return "iPad Pro (11-inch) (4th generation)"
case "iPad16,3", "iPad16,4": return "iPad Pro (11-inch) (M4)"
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 "iPad14,5", "iPad14,6": return "iPad Pro (12.9-inch) (6th generation)"
case "iPad16,5", "iPad16,6": return "iPad Pro (13-inch) (M4)"
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", "AppleTV11,1", "AppleTV14,1": return "Apple TV 4K"
case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))"
default: return identifier
}
#elseif os(visionOS)
switch identifier {
case "RealityDevice14,1": return "Apple Vision Pro"
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:
Upvotes: 1289
Reputation: 566
Here's the solution updated for October 2024. It includes the most recent iPhone, iPad, Watch, iPod, Apple TV, and HomePod:
extension UIDevice {
static 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 {
// MARK: - iPhone
case "i386", "x86_64", "arm64": return "iPhone Simulator"
case "iPhone1,1": return "iPhone"
case "iPhone1,2": return "iPhone 3G"
case "iPhone2,1": return "iPhone 3GS"
case "iPhone3,1": return "iPhone 4"
case "iPhone3,2": return "iPhone 4 GSM Rev A"
case "iPhone3,3": return "iPhone 4 CDMA"
case "iPhone4,1": return "iPhone 4S"
case "iPhone5,1": return "iPhone 5 (GSM)"
case "iPhone5,2": return "iPhone 5 (GSM+CDMA)"
case "iPhone5,3": return "iPhone 5C (GSM)"
case "iPhone5,4": return "iPhone 5C (Global)"
case "iPhone6,1": return "iPhone 5S (GSM)"
case "iPhone6,2": return "iPhone 5S (Global)"
case "iPhone7,1": return "iPhone 6 Plus"
case "iPhone7,2": return "iPhone 6"
case "iPhone8,1": return "iPhone 6s"
case "iPhone8,2": return "iPhone 6s Plus"
case "iPhone8,4": return "iPhone SE (GSM)"
case "iPhone9,1": return "iPhone 7"
case "iPhone9,2": return "iPhone 7 Plus"
case "iPhone9,3": return "iPhone 7"
case "iPhone9,4": return "iPhone 7 Plus"
case "iPhone10,1": return "iPhone 8"
case "iPhone10,2": return "iPhone 8 Plus"
case "iPhone10,3": return "iPhone X Global"
case "iPhone10,4": return "iPhone 8"
case "iPhone10,5": return "iPhone 8 Plus"
case "iPhone10,6": return "iPhone X GSM"
case "iPhone11,2": return "iPhone XS"
case "iPhone11,4": return "iPhone XS Max"
case "iPhone11,6": return "iPhone XS Max Global"
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 Gen"
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,2": return "iPhone 13 Pro"
case "iPhone14,3": return "iPhone 13 Pro Max"
case "iPhone14,4": return "iPhone 13 Mini"
case "iPhone14,5": return "iPhone 13"
case "iPhone14,6": return "iPhone SE 3rd Gen"
case "iPhone14,7": return "iPhone 14"
case "iPhone14,8": return "iPhone 14 Plus"
case "iPhone15,2": return "iPhone 14 Pro"
case "iPhone15,3": return "iPhone 14 Pro Max"
case "iPhone15,4": return "iPhone 15"
case "iPhone15,5": return "iPhone 15 Plus"
case "iPhone16,1": return "iPhone 15 Pro"
case "iPhone16,2": return "iPhone 15 Pro Max"
case "iPhone17,1": return "iPhone 16 Pro"
case "iPhone17,2": return "iPhone 16 Pro Max"
case "iPhone17,3": return "iPhone 16"
case "iPhone17,4": return "iPhone 16 Plus"
// MARK: - iPod
case "iPod1,1": return "1st Gen iPod"
case "iPod2,1": return "2nd Gen iPod"
case "iPod3,1": return "3rd Gen iPod"
case "iPod4,1": return "4th Gen iPod"
case "iPod5,1": return "5th Gen iPod"
case "iPod7,1": return "6th Gen iPod"
case "iPod9,1": return "7th Gen iPod"
// MARK: - iPad
case "iPad1,1": return "iPad"
case "iPad1,2": return "iPad 3G"
case "iPad2,1": return "2nd Gen iPad"
case "iPad2,2": return "2nd Gen iPad GSM"
case "iPad2,3": return "2nd Gen iPad CDMA"
case "iPad2,4": return "2nd Gen iPad New Revision"
case "iPad3,1": return "3rd Gen iPad"
case "iPad3,2": return "3rd Gen iPad CDMA"
case "iPad3,3": return "3rd Gen iPad GSM"
case "iPad2,5": return "iPad mini"
case "iPad2,6": return "iPad mini GSM+LTE"
case "iPad2,7": return "iPad mini CDMA+LTE"
case "iPad3,4": return "4th Gen iPad"
case "iPad3,5": return "4th Gen iPad GSM+LTE"
case "iPad3,6": return "4th Gen iPad CDMA+LTE"
case "iPad4,1": return "iPad Air (WiFi)"
case "iPad4,2": return "iPad Air (GSM+CDMA)"
case "iPad4,3": return "1st Gen iPad Air (China)"
case "iPad4,4": return "iPad mini Retina (WiFi)"
case "iPad4,5": return "iPad mini Retina (GSM+CDMA)"
case "iPad4,6": return "iPad mini Retina (China)"
case "iPad4,7": return "iPad mini 3 (WiFi)"
case "iPad4,8": return "iPad mini 3 (GSM+CDMA)"
case "iPad4,9": return "iPad Mini 3 (China)"
case "iPad5,1": return "iPad mini 4 (WiFi)"
case "iPad5,2": return "4th Gen iPad mini (WiFi+Cellular)"
case "iPad5,3": return "iPad Air 2 (WiFi)"
case "iPad5,4": return "iPad Air 2 (Cellular)"
case "iPad6,3": return "iPad Pro (9.7 inch, WiFi)"
case "iPad6,4": return "iPad Pro (9.7 inch, WiFi+LTE)"
case "iPad6,7": return "iPad Pro (12.9 inch, WiFi)"
case "iPad6,8": return "iPad Pro (12.9 inch, WiFi+LTE)"
case "iPad6,11": return "iPad (2017)"
case "iPad6,12": return "iPad (2017)"
case "iPad7,1": return "iPad Pro 2nd Gen (WiFi)"
case "iPad7,2": return "iPad Pro 2nd Gen (WiFi+Cellular)"
case "iPad7,3": return "iPad Pro 10.5-inch 2nd Gen"
case "iPad7,4": return "iPad Pro 10.5-inch 2nd Gen"
case "iPad7,5": return "iPad 6th Gen (WiFi)"
case "iPad7,6": return "iPad 6th Gen (WiFi+Cellular)"
case "iPad7,11": return "iPad 7th Gen 10.2-inch (WiFi)"
case "iPad7,12": return "iPad 7th Gen 10.2-inch (WiFi+Cellular)"
case "iPad8,1": return "iPad Pro 11 inch 3rd Gen (WiFi)"
case "iPad8,2": return "iPad Pro 11 inch 3rd Gen (1TB, WiFi)"
case "iPad8,3": return "iPad Pro 11 inch 3rd Gen (WiFi+Cellular)"
case "iPad8,4": return "iPad Pro 11 inch 3rd Gen (1TB, WiFi+Cellular)"
case "iPad8,5": return "iPad Pro 12.9 inch 3rd Gen (WiFi)"
case "iPad8,6": return "iPad Pro 12.9 inch 3rd Gen (1TB, WiFi)"
case "iPad8,7": return "iPad Pro 12.9 inch 3rd Gen (WiFi+Cellular)"
case "iPad8,8": return "iPad Pro 12.9 inch 3rd Gen (1TB, WiFi+Cellular)"
case "iPad8,9": return "iPad Pro 11 inch 4th Gen (WiFi)"
case "iPad8,10": return "iPad Pro 11 inch 4th Gen (WiFi+Cellular)"
case "iPad8,11": return "iPad Pro 12.9 inch 4th Gen (WiFi)"
case "iPad8,12": return "iPad Pro 12.9 inch 4th Gen (WiFi+Cellular)"
case "iPad11,1": return "iPad mini 5th Gen (WiFi)"
case "iPad11,2": return "iPad mini 5th Gen"
case "iPad11,3": return "iPad Air 3rd Gen (WiFi)"
case "iPad11,4": return "iPad Air 3rd Gen"
case "iPad11,6": return "iPad 8th Gen (WiFi)"
case "iPad11,7": return "iPad 8th Gen (WiFi+Cellular)"
case "iPad12,1": return "iPad 9th Gen (WiFi)"
case "iPad12,2": return "iPad 9th Gen (WiFi+Cellular)"
case "iPad14,1": return "iPad mini 6th Gen (WiFi)"
case "iPad14,2": return "iPad mini 6th Gen (WiFi+Cellular)"
case "iPad13,1": return "iPad Air 4th Gen (WiFi)"
case "iPad13,2": return "iPad Air 4th Gen (WiFi+Cellular)"
case "iPad13,4": return "iPad Pro 11 inch 5th Gen"
case "iPad13,5": return "iPad Pro 11 inch 5th Gen"
case "iPad13,6": return "iPad Pro 11 inch 5th Gen"
case "iPad13,7": return "iPad Pro 11 inch 5th Gen"
case "iPad13,8": return "iPad Pro 12.9 inch 5th Gen"
case "iPad13,9": return "iPad Pro 12.9 inch 5th Gen"
case "iPad13,10": return "iPad Pro 12.9 inch 5th Gen"
case "iPad13,11": return "iPad Pro 12.9 inch 5th Gen"
case "iPad13,16": return "iPad Air 5th Gen (WiFi)"
case "iPad13,17": return "iPad Air 5th Gen (WiFi+Cellular)"
case "iPad13,18": return "iPad 10th Gen"
case "iPad13,19": return "iPad 10th Gen"
case "iPad14,3": return "iPad Pro 11 inch 4th Gen"
case "iPad14,4": return "iPad Pro 11 inch 4th Gen"
case "iPad14,5": return "iPad Pro 12.9 inch 6th Gen"
case "iPad14,6": return "iPad Pro 12.9 inch 6th Gen"
case "iPad14,8": return "iPad Air 6th Gen"
case "iPad14,9": return "iPad Air 6th Gen"
case "iPad14,10": return "iPad Air 7th Gen"
case "iPad14,11": return "iPad Air 7th Gen"
case "iPad16,3": return "iPad Pro 11 inch 5th Gen"
case "iPad16,4": return "iPad Pro 11 inch 5th Gen"
case "iPad16,5": return "iPad Pro 12.9 inch 7th Gen"
case "iPad16,6": return "iPad Pro 12.9 inch 7th Gen"
// MARK: - Watch
case "Watch1,1": return "Apple Watch 38mm case"
case "Watch1,2": return "Apple Watch 42mm case"
case "Watch2,6": return "Apple Watch Series 1 38mm case"
case "Watch2,7": return "Apple Watch Series 1 42mm case"
case "Watch2,3": return "Apple Watch Series 2 38mm case"
case "Watch2,4": return "Apple Watch Series 2 42mm case"
case "Watch3,1": return "Apple Watch Series 3 38mm case (GPS+Cellular)"
case "Watch3,2": return "Apple Watch Series 3 42mm case (GPS+Cellular)"
case "Watch3,3": return "Apple Watch Series 3 38mm case (GPS)"
case "Watch3,4": return "Apple Watch Series 3 42mm case (GPS)"
case "Watch4,1": return "Apple Watch Series 4 40mm case (GPS)"
case "Watch4,2": return "Apple Watch Series 4 44mm case (GPS)"
case "Watch4,3": return "Apple Watch Series 4 40mm case (GPS+Cellular)"
case "Watch4,4": return "Apple Watch Series 4 44mm case (GPS+Cellular)"
case "Watch5,1": return "Apple Watch Series 5 40mm case (GPS)"
case "Watch5,2": return "Apple Watch Series 5 44mm case (GPS)"
case "Watch5,3": return "Apple Watch Series 5 40mm case (GPS+Cellular)"
case "Watch5,4": return "Apple Watch Series 5 44mm case (GPS+Cellular)"
case "Watch5,9": return "Apple Watch SE 40mm case (GPS)"
case "Watch5,10": return "Apple Watch SE 44mm case (GPS)"
case "Watch5,11": return "Apple Watch SE 40mm case (GPS+Cellular)"
case "Watch5,12": return "Apple Watch SE 44mm case (GPS+Cellular)"
case "Watch6,1": return "Apple Watch Series 6 40mm case (GPS)"
case "Watch6,2": return "Apple Watch Series 6 44mm case (GPS)"
case "Watch6,3": return "Apple Watch Series 6 40mm case (GPS+Cellular)"
case "Watch6,4": return "Apple Watch Series 6 44mm case (GPS+Cellular)"
case "Watch6,6": return "Apple Watch Series 7 41mm case (GPS)"
case "Watch6,7": return "Apple Watch Series 7 45mm case (GPS)"
case "Watch6,8": return "Apple Watch Series 7 41mm case (GPS+Cellular)"
case "Watch6,9": return "Apple Watch Series 7 45mm case (GPS+Cellular)"
case "Watch6,10": return "Apple Watch SE 40mm case (GPS)"
case "Watch6,11": return "Apple Watch SE 44mm case (GPS)"
case "Watch6,12": return "Apple Watch SE 40mm case (GPS+Cellular)"
case "Watch6,13": return "Apple Watch SE 44mm case (GPS+Cellular)"
case "Watch6,14": return "Apple Watch Series 8 41mm case (GPS)"
case "Watch6,15": return "Apple Watch Series 8 45mm case (GPS)"
case "Watch6,16": return "Apple Watch Series 8 41mm case (GPS+Cellular)"
case "Watch6,17": return "Apple Watch Series 8 45mm case (GPS+Cellular)"
case "Watch6,18": return "Apple Watch Ultra"
case "Watch7,1": return "Apple Watch Series 9 41mm case (GPS)"
case "Watch7,2": return "Apple Watch Series 9 45mm case (GPS)"
case "Watch7,3": return "Apple Watch Series 9 41mm case (GPS+Cellular)"
case "Watch7,4": return "Apple Watch Series 9 45mm case (GPS+Cellular)"
case "Watch7,5": return "Apple Watch Ultra 2"
// MARK: - Apple TV
case "AppleTV5,3": return "Apple TV"
case "AppleTV6,2": return "Apple TV 4K"
// MARK: - HomePod
case "AudioAccessory1,1": return "HomePod"
case "AudioAccessory5,1": return "HomePod mini"
// MARK: - Unrecognized
default: return identifier
}
}
}
Usage:
UIDevice.modelName
Upvotes: 18
Reputation: 663
Here is more additional system info
extension UIDevice {
static var deviceModel: String {
var size: Int = 0
sysctlbyname("hw.model", nil, &size, nil, 0)
var model = [CChar](repeating: 0, count: size)
sysctlbyname("hw.model", &model, &size, nil, 0)
let abiType = String(cString: model)
return abiType
}
struct OSInfo {
let sysname: String?
let nodename: String?
let release: String?
let version: String?
let machine: String?
}
static func osInfo() -> OSInfo {
var systemInfo = utsname()
uname(&systemInfo)
let sysname = withUnsafePointer(to: &systemInfo.sysname) {
$0.withMemoryRebound(to: Int8.self, capacity: 1) { String(cString: $0) }
}
let nodename = withUnsafePointer(to: &systemInfo.nodename) {
$0.withMemoryRebound(to: Int8.self, capacity: 1) { String(cString: $0) }
}
let release = withUnsafePointer(to: &systemInfo.release) {
$0.withMemoryRebound(to: Int8.self, capacity: 1) { String(cString: $0) }
}
let version = withUnsafePointer(to: &systemInfo.version) {
$0.withMemoryRebound(to: Int8.self, capacity: 1) { String(cString: $0) }
}
let machine = withUnsafePointer(to: &systemInfo.machine) {
$0.withMemoryRebound(to: Int8.self, capacity: 1) { String(cString: $0) }
}
return OSInfo(sysname: sysname, nodename: nodename, release: release, version: version, machine: machine)
}
static var osBuildNumber: String? {
let versionString = ProcessInfo.processInfo.operatingSystemVersionString
let pattern = "Build (\\w+)"
do {
let regex = try NSRegularExpression(pattern: pattern, options: [])
let nsString = versionString as NSString
let results = regex.matches(in: versionString, options: [], range: NSRange(location: 0, length: nsString.length))
if let match = results.first {
let buildNumberRange = match.range(at: 1)
return nsString.substring(with: buildNumberRange)
}
} catch {
print("Error creating regex: \(error)")
}
return nil
}
}
Upvotes: 0
Reputation: 35402
(always checked and updated!)
with the last: iPad 10th generation, iPhone 16 ALL VERSIONS 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)
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
iPad10 = "iPad 10", //iPad 2022
//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",
iPhone14 = "iPhone 14",
iPhone14Plus = "iPhone 14 Plus",
iPhone14Pro = "iPhone 14 Pro",
iPhone14ProMax = "iPhone 14 Pro Max",
iPhone15 = "iPhone 15",
iPhone15Plus = "iPhone 15 Plus",
iPhone15Pro = "iPhone 15 Pro",
iPhone15ProMax = "iPhone 15 Pro Max",
iPhone16 = "iPhone 16" ,
iPhone16Plus = "iPhone 16 Plus",
iPhone16Pro = "iPhone 16 Pro",
iPhone16ProMax = "iPhone 16 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",
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",
AppleTV3_4K = "Apple TV 4K 3gen",
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,
"iPad13,18" : .iPad10,
"iPad13,19" : .iPad10,
//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,
"iPhone14,7" : .iPhone14,
"iPhone14,8" : .iPhone14Plus,
"iPhone15,2" : .iPhone14Pro,
"iPhone15,3" : .iPhone14ProMax,
"iPhone15,4" : .iPhone15,
"iPhone15,5" : .iPhone15Plus,
"iPhone16,1" : .iPhone15Pro,
"iPhone16,2" : .iPhone15ProMax,
"iPhone17,3" : .iPhone16,
"iPhone17,4" : .iPhone16Plus,
"iPhone17,1" : .iPhone16Pro,
"iPhone17,2" : .iPhone16ProMax,
// 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,
"AppleTV14,1" : .AppleTV3_4K
]
guard let mcode = modelCode, let model = modelMap[mcode] else { return Model.unrecognized }
if model == .simulator {
if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
if let simModel = modelMap[simModelCode] {
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.
Upvotes: 268
Reputation: 1536
If you want the 'human-readable' device name for running unit tests in Simulator, e.g. iPhone SE (3rd generation) instead of iPhone14,6, use Apple's own "SIMULATOR_DEVICE_NAME"
:
let deviceName = ProcessInfo().environment["SIMULATOR_DEVICE_NAME"] ?? "unknown"
print(deviceName) // Prints: iPhone SE (3rd generation)
💡 This is the same naming you find in the Xcode run destinations dropdown, as well as in xcrun simctl list
.
There's no (longer) need to use libraries for this use case, nor your own mapping of "SIMULATOR_MODEL_IDENTIFIER"
, so we have an opportunity to clean up our code bases. 🧹
Upvotes: 2
Reputation: 101
Works for me
var sysinfo = utsname()
uname(&sysinfo)
let data = Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN))
let model = String(cString: [UInt8](data)) //iPhone13,1
Upvotes: 2
Reputation: 1713
I recently worked on the development of this swift package:
https://github.com/EmilioOjeda/Device
The main advantage it has - I think - is that it is code-generated. So whenever a new Xcode version is released, all I have to do is to run a script and get the swift package updated.
How does code generation work?
It reads and parses the devices' data from Xcode's databases (per platform) to identify the device that is running - and provide the information for it.
And it's usage...
import Device
// or => 'import iPhoneOSDevice' <= iPhoneOS-only device data
// or => 'import tvOSDevice' <= tvOS-only device data
// A representation of the running device - it could be either actual or simulated.
let device = Device.current
// It is 'true' when running on a physical device.
_ = device.isDevice
// It is 'true' when running on a simulator instance.
_ = device.isSimulator
// It is 'true' when the device does not match either simulators or physical devices.
_ = device.isUnknown
// The identifier for the device.
// i.e.: 'iPhone15,3'
let id = device.id
// The known/commercial name of the device.
// i.e.: 'iPhone 14 Pro Max'
let model = device.model
Upvotes: 3
Reputation: 1967
Here is a new library for detecting apple devices
import DeviceDetector
let detector = DeviceDetector.shared
let deviceName = detector.currentDeviceName
let deviceSet = detector.currentDevice
let information = """
Model: \(deviceName)
iPhone?: \(detector.isiPhone)
iPad?: \(detector.isiPad)
Notch?: \(detector.hasSafeArea)
4inch?: \(DeviceSet.iPhone4inchSet.contains(deviceSet))
4.7inch?: \(DeviceSet.iPhone4_7inchSet.contains(deviceSet))
iPhoneSE?: \(DeviceSet.iPhoneSESet.contains(deviceSet))
iPhonePlus?: \(DeviceSet.iPhonePlusSet.contains(deviceSet))
iPadPro?: \(DeviceSet.iPadProSet.contains(deviceSet))
"""
Upvotes: 1
Reputation: 312
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.
Upvotes: 18
Reputation: 35402
the asynchronous library that gives you the answer from theiphonewiki
A crazy little experiment for automation fans like me. I made this algorithm that reads the identification code of the device, physical or simulated, and load the theiphonewiki page to extrapolate the model name based on the identification code (example iPhone11,2 -> iPhone XS). The algorithm interfaces with the WIKI page using the internal Wiki API Sandbox tool that allows you to have a JSON response, however the content is not obtainable in JSON (just the part that was needed, that is the wikitables) so I parsed the HTML content to get to the device name, without using third parts HTML parsing libraries.
PROS: always updated, you don't need to add new devices
CONS: asyncronous answer using the wiki page from web
P.S. Feel free to improve my code to get an even more precise result and a more elegant syntax P.S.S. If you need a more immediate answer use my previous answer here in this page
public extension UIDevice {
var identifier: String {
var systemInfo = utsname()
uname(&systemInfo)
let modelCode = withUnsafePointer(to: &systemInfo.machine) {
$0.withMemoryRebound(to: CChar.self, capacity: 1) {
ptr in String.init(validatingUTF8: ptr)
}
}
if modelCode == "x86_64" {
if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
if let simMap = String(validatingUTF8: simModelCode) {
return simMap
}
}
}
return modelCode ?? "?unrecognized?"
}
}
class WikiDevice {
static func model(_ completion: @escaping ((String) -> ())){
let unrecognized = "?unrecognized?"
guard let wikiUrl=URL(string:"https://www.theiphonewiki.com//w/api.php?action=parse&format=json&page=Models") else { return completion(unrecognized) }
var identifier: String {
var systemInfo = utsname()
uname(&systemInfo)
let modelCode = withUnsafePointer(to: &systemInfo.machine) {
$0.withMemoryRebound(to: CChar.self, capacity: 1) {
ptr in String.init(validatingUTF8: ptr)
}
}
if modelCode == "x86_64" {
if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
if let simMap = String(validatingUTF8: simModelCode) {
return simMap
}
}
}
return modelCode ?? unrecognized
}
guard identifier != unrecognized else { return completion(unrecognized)}
let request = URLRequest(url: wikiUrl)
URLSession.shared.dataTask(with: request) { (data, response, error) in
do {
guard let data = data,
let response = response as? HTTPURLResponse, (200 ..< 300) ~= response.statusCode,
error == nil else { return completion(unrecognized) }
guard let convertedString = String(data: data, encoding: String.Encoding.utf8) else { return completion(unrecognized) }
var wikiTables = convertedString.components(separatedBy: "wikitable")
wikiTables.removeFirst()
var tables = [[String]]()
wikiTables.enumerated().forEach{ index,table in
let rawRows = table.components(separatedBy: #"<tr>\n<td"#)
var counter = 0
var rows = [String]()
while counter < rawRows.count {
let rawRow = rawRows[counter]
if let subRowsNum = rawRow.components(separatedBy: #"rowspan=\""#).dropFirst().compactMap({ sub in
(sub.range(of: #"\">"#)?.lowerBound).flatMap { endRange in
String(sub[sub.startIndex ..< endRange])
}
}).first {
if let subRowsTot = Int(subRowsNum) {
var otherRows = ""
for i in counter..<counter+subRowsTot {
otherRows += rawRows[i]
}
let row = rawRow + otherRows
rows.append(row)
counter += subRowsTot-1
}
} else {
rows.append(rawRows[counter])
}
counter += 1
}
tables.append(rows)
}
for table in tables {
if let rowIndex = table.firstIndex(where: {$0.lowercased().contains(identifier.lowercased())}) {
let rows = table[rowIndex].components(separatedBy: "<td>")
if rows.count>0 {
if rows[0].contains("title") { //hyperlink
if let (cleanedGen) = rows[0].components(separatedBy: #">"#).dropFirst().compactMap({ sub in
(sub.range(of: "</")?.lowerBound).flatMap { endRange in
String(sub[sub.startIndex ..< endRange]).replacingOccurrences(of: #"\n"#, with: "")
}
}).first {
completion(cleanedGen)
}
} else {
let raw = rows[0].replacingOccurrences(of: "<td>", with: "")
let cleanedGen = raw.replacingOccurrences(of: #"\n"#, with: "")
completion(cleanedGen)
}
return
}
}
}
completion(unrecognized)
}
}.resume()
}
}
var deviceModel:String = ""
WikiDevice.model { (model) in
print("Using WikiDevice, running on: \(model)")
deviceModel = model
}
Using WikiDevice, running on: iPhone 11 Pro Max
If you need to test this library you can download the test project from here
Upvotes: 7
Reputation: 1795
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
}
}
}
Upvotes: 40
Reputation: 432
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)
Upvotes: 1
Reputation: 52221
/// 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"
}
Upvotes: 33
Reputation: 12625
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
}
}
Upvotes: 162
Reputation: 5145
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
}
Upvotes: 5
Reputation: 2870
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)
}
Upvotes: 143
Reputation: 5202
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;
}
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".
Upvotes: 1
Reputation: 151
You can use BDLocalizedDevicesModels framework to parse device info and get the name.
Then just call UIDevice.currentDevice.productName
in your code.
Upvotes: 3
Reputation: 5379
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
}
}
}
Upvotes: 2
Reputation: 1062
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
}
Upvotes: -3
Reputation: 2384
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:
}
Upvotes: 2
Reputation: 3817
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
}
}
}
Upvotes: 6
Reputation: 2758
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
Upvotes: 0
Reputation: 11666
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"
Upvotes: 2
Reputation: 7413
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
}
}
Upvotes: 4
Reputation: 19
struct utsname systemInfo;
uname(&systemInfo);
NSString* deviceModel = [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
Upvotes: 0
Reputation: 11494
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
}
}
}
Upvotes: 9
Reputation: 516
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!)!
}
Upvotes: 3
Reputation: 109
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
}
}
}
Upvotes: 6