How to detect device model by macro? i had using something like this but the result on the simulator alway IS_IPHONE_5
#define IS_IPAD (UI_USER_INTERFACE_IDI
Update Xcode 11 / Swift 5.1:
enum UIUserInterfaceIdiom : Int
{
case Unspecified
case Phone
case Pad
}
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_8 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6_8P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_11_PRO = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_XR_SMAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_XS_MAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_11 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPHONE_11_PRO_MAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO10 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1112.0
static let IS_IPAD_PRO12 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
static let IS_IPAD_ALL = UIDevice.current.userInterfaceIdiom == .pad
static let IS_IPHONE_NOTCH_DEVICE = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 896.0 || ScreenSize.SCREEN_MAX_LENGTH == 812.0)
}
struct Version{
static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0 && Version.SYS_VERSION_FLOAT < 11.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0 && Version.SYS_VERSION_FLOAT < 12.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0 && Version.SYS_VERSION_FLOAT < 13.0)
static let iOS13 = (Version.SYS_VERSION_FLOAT >= 13.0)
}
struct VersionAndNewer {
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0)
static let iOS13 = (Version.SYS_VERSION_FLOAT >= 13.0)
}
Hi i updated to Xcode10 / Swift 4.2 and the new sizes for IPhone XS / XSMAX /XR
with detection of Notch-IPhones.
Hope this helps someone.
enum UIUserInterfaceIdiom : Int
{
case Unspecified
case Phone
case Pad
}
struct ScreenSize
{
static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType
{
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_8 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let IS_IPHONE_6_8P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
static let IS_IPHONE_XR_SMAX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 896.0
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
static let IS_IPAD_PRO10 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1112.0
static let IS_IPAD_PRO12 = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
static let IS_IPHONE_NOTCH_DEVICE = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 896.0 || ScreenSize.SCREEN_MAX_LENGTH == 812.0)
}
struct Version{
static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0 && Version.SYS_VERSION_FLOAT < 11.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0 && Version.SYS_VERSION_FLOAT < 12.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0)
}
struct VersionAndNewer {
static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0)
static let iOS10 = (Version.SYS_VERSION_FLOAT >= 10.0)
static let iOS11 = (Version.SYS_VERSION_FLOAT >= 11.0)
static let iOS12 = (Version.SYS_VERSION_FLOAT >= 12.0)
}
import UIKit
public enum DisplayType {
case unknown
case iphone4
case iphone5
case iphone6
case iphone6plus
static let iphone7 = iphone6
static let iphone7plus = iphone6plus
case iphoneX
}
public final class Display {
class var width:CGFloat { return UIScreen.main.bounds.size.width }
class var height:CGFloat { return UIScreen.main.bounds.size.height }
class var maxLength:CGFloat { return max(width, height) }
class var minLength:CGFloat { return min(width, height) }
class var zoomed:Bool { return UIScreen.main.nativeScale >= UIScreen.main.scale }
class var retina:Bool { return UIScreen.main.scale >= 2.0 }
class var phone:Bool { return UIDevice.current.userInterfaceIdiom == .phone }
class var pad:Bool { return UIDevice.current.userInterfaceIdiom == .pad }
class var carplay:Bool { return UIDevice.current.userInterfaceIdiom == .carPlay }
class var tv:Bool { return UIDevice.current.userInterfaceIdiom == .tv }
class var typeIsLike:DisplayType {
if phone && maxLength < 568 {
return .iphone4
}
else if phone && maxLength == 568 {
return .iphone5
}
else if phone && maxLength == 667 {
return .iphone6
}
else if phone && maxLength == 736 {
return .iphone6plus
}
else if phone && maxLength == 812 {
return .iphoneX
}
return .unknown
}
}
See it in action https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346
Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_ZOOMED (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
#define IS_IPHONE_X (IS_IPHONE && SCREEN_MAX_LENGTH == 812.0)
Usage: http://pastie.org/9687735
Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.
I encountered the problem while migrating from an iOS 7 project to a iOS 8 project, since I didn't add a launch screen scene to my project.
In this case the screen size for iPhone 6 and 6+ are as iPhone 5.
See from apple documentation; You use a launch XIB or storyboard file to indicate that your app runs on iPhone 6 Plus or iPhone 6.
import Foundation
import UIKit
public enum IADisplayType {
// unknow device
case unspecified
// iPhone
case unknowiPhone
case iPhone3GS
case iPhone4
static let iPhone4s = iPhone5
case iPhone5
static let iPhone5s = iPhone5
static let iPhoneSE = iPhone5
case iPhone6
case iPhone6Plus
static let iPhone6s = iPhone6
static let iPhone6sPlus = iPhone6Plus
static let iPhone7 = iPhone6
static let iPhone7Plus = iPhone6Plus
static let iPhone8 = iPhone6
static let iPhone8Plus = iPhone6Plus
case iPhoneX
// iPad
case unknowiPad
case iPad79
static let iPad97 = iPad79
case iPad105
case iPad129
// Apple CarPlay
case carPlay
// Apple TV
case tv
}
public final class IADisplayManager {
// MARK: - public interface
// singleton
static var shared: IADisplayManager {
get {
return IADisplayManager()
}
}
// get current device type
public var currentType: IADisplayType {
get {
return calCurrentType()
}
}
// device current Native Resolution
public var nativeResolution: CGSize {
get {
return UIScreen.main.nativeBounds.size
}
}
// device current Native Scale Factor
public var nativeScaleFactor: CGFloat {
get {
return UIScreen.main.nativeScale
}
}
// device current Interface Idiom
public var interfaceIdiom: UIUserInterfaceIdiom {
get {
return UIDevice().userInterfaceIdiom
}
}
fileprivate init() {}
// MARK: - private interface
fileprivate func calCurrentType() -> IADisplayType {
typealias Type = IADisplayType
// unknown device
if interfaceIdiom == .unspecified { return Type.unspecified }
// iPhone && iPod Touch
else if interfaceIdiom == .phone {
if nativeScaleFactor == 1.0 && nativeResolution == CGSize(width: 320, height: 480) { return Type.iPhone3GS }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 640, height: 960) { return Type.iPhone4 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 640, height: 1136) { return Type.iPhone5 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 750, height: 1334) { return Type.iPhone6 }
else if (nativeScaleFactor-2.608) < 0.001 && nativeResolution == CGSize(width: 1080, height: 1920) { return Type.iPhone6Plus }
else if nativeScaleFactor == 3.0 && nativeResolution == CGSize(width: 1125, height: 2436) { return Type.iPhoneX }
else { return Type.unknowiPhone }
}
// iPad
else if interfaceIdiom == .pad {
if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 1536, height: 2048) { return Type.iPad79 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 2224, height: 1668) { return Type.iPad105 }
else if nativeScaleFactor == 2.0 && nativeResolution == CGSize(width: 2048, height: 2732) { return Type.iPad129 }
else { return Type.unknowiPad }
}
// Apple CarPlay
else if interfaceIdiom == .carPlay { return Type.carPlay }
// Apple TV
else if interfaceIdiom == .tv { return Type.tv }
// unknown device
else { return Type.unspecified }
}
}
I use a class that pulls actual system info. Just have to make sure all device types are up to date.
#import "Macros.h"
@implementation Macros
+ (BOOL)IS_IPHONE_6_PLUS {
return [[self deviceType] isEqualToString:@"iPhone 6 Plus"] || [[self deviceType] isEqualToString:@"iPhone 6S Plus"];
}
+ (BOOL)IS_IPHONE_6 {
return [[self deviceType] isEqualToString:@"iPhone 6"] || [[self deviceType] isEqualToString:@"iPhone 6S"];
}
+ (BOOL)IS_SIMULATOR {
return [[self deviceType] isEqualToString:@"32-bit Simulator"]
|| [[self deviceType] isEqualToString:@"64-bit Simulator"];
}
+ (BOOL)IS_IPHONE_5 {
NSString *device = [self deviceType];
BOOL result = [device isEqualToString:@"iPhone 5(GSM)"] || [device isEqualToString:@"iPhone 5(GSM+CDMA)"]
|| [device isEqualToString:@"iPhone 5C(GSM)"] || [device isEqualToString:@"iPhone 5C(GSM+CDMA)"]
|| [device isEqualToString:@"iPhone 5S(GSM)"] || [device isEqualToString:@"iPhone 5S(GSM+CDMA)"];
return result;
}
/*
@"i386" on 32-bit Simulator
@"x86_64" on 64-bit Simulator
@"iPod1,1" on iPod Touch
@"iPod2,1" on iPod Touch Second Generation
@"iPod3,1" on iPod Touch Third Generation
@"iPod4,1" on iPod Touch Fourth Generation
@"iPod5,1" on iPod Touch Fifth Generation
@"iPhone1,1" on iPhone
@"iPhone1,2" on iPhone 3G
@"iPhone2,1" on iPhone 3GS
@"iPad1,1" on iPad
@"iPad2,1" on iPad 2
@"iPad3,1" on 3rd Generation iPad
@"iPad3,2": on iPad 3(GSM+CDMA)
@"iPad3,3": on iPad 3(GSM)
@"iPad3,4": on iPad 4(WiFi)
@"iPad3,5": on iPad 4(GSM)
@"iPad3,6": on iPad 4(GSM+CDMA)
@"iPhone3,1" on iPhone 4
@"iPhone4,1" on iPhone 4S
@"iPad3,4" on 4th Generation iPad
@"iPad2,5" on iPad Mini
@"iPhone5,1" on iPhone 5(GSM)
@"iPhone5,2" on iPhone 5(GSM+CDMA)
@"iPhone5,3 on iPhone 5c(GSM)
@"iPhone5,4" on iPhone 5c(GSM+CDMA)
@"iPhone6,1" on iPhone 5s(GSM)
@"iPhone6,2" on iPhone 5s(GSM+CDMA)
@"iPhone7,1" on iPhone 6 Plus
@"iPhone7,2" on iPhone 6
@"iPhone8,1" on iPhone 6
@"iPhone8,2" on iPhone 6 Plus ...Yes Apple switched the order...
*/
+ (NSString *)deviceType {
struct utsname systemInfo;
uname(&systemInfo);
NSString *result = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
// https://www.theiphonewiki.com/wiki/Models
NSDictionary *matches = @{
@"i386" : @"32-bit Simulator",
@"x86_64" : @"64-bit Simulator",
@"iPod1,1" : @"iPod Touch",
@"iPod2,1" : @"iPod Touch Second Generation",
@"iPod3,1" : @"iPod Touch Third Generation",
@"iPod4,1" : @"iPod Touch Fourth Generation",
@"iPod5,1" : @"iPod Touch Fifth Generation",
@"iPad1,1" : @"iPad",
@"iPad2,1" : @"iPad 2",
@"iPad2,2" : @"iPad 2",
@"iPad2,3" : @"iPad 2",
@"iPad2,4" : @"iPad 2",
@"iPad2,5" : @"iPad Mini",
@"iPad2,6" : @"iPad Mini",
@"iPad2,7" : @"iPad Mini",
@"iPad3,1" : @"iPad 3",
@"iPad3,2" : @"iPad 3(GSM+CDMA)",
@"iPad3,3" : @"iPad 3(GSM)",
@"iPad3,4" : @"iPad 4(WiFi)",
@"iPad3,5" : @"iPad 4(GSM)",
@"iPad3,6" : @"iPad 4(GSM+CDMA)",
@"iPad4,1" : @"iPad Air",
@"iPad4,2" : @"iPad Air",
@"iPad4,3" : @"iPad Air",
@"iPad4,4" : @"iPad Mini 2",
@"iPad4,5" : @"iPad Mini 2",
@"iPad4,6" : @"iPad Mini 2",
@"iPad4,7" : @"iPad Mini 3",
@"iPad4,8" : @"iPad Mini 3",
@"iPad4,9" : @"iPad Mini 3",
@"iPad5,1" : @"iPad Mini 4",
@"iPad5,2" : @"iPad Mini 4",
@"iPad5,3" : @"iPad Air 2",
@"iPad5,4" : @"iPad Air 2",
@"iPad6,3" : @"iPad Pro (9.7in)",
@"iPad6,4" : @"iPad Pro (9.7in)",
@"iPad6,7" : @"iPad Pro (12.9in)",
@"iPad6,8" : @"iPad Pro (12.9in)",
@"iPhone1,1" : @"iPhone",
@"iPhone1,2" : @"iPhone 3G",
@"iPhone2,1" : @"iPhone 3GS",
@"iPhone3,1" : @"iPhone 4",
@"iPhone3,3" : @"iPhone 4",
@"iPhone4,1" : @"iPhone 4S",
@"iPhone5,1" : @"iPhone 5(GSM)",
@"iPhone5,2" : @"iPhone 5(GSM+CDMA)",
@"iPhone5,3" : @"iPhone 5C(GSM)",
@"iPhone5,4" : @"iPhone 5C(GSM+CDMA)",
@"iPhone6,1" : @"iPhone 5S(GSM)",
@"iPhone6,2" : @"iPhone 5S(GSM+CDMA)",
@"iPhone7,1" : @"iPhone 6 Plus",
@"iPhone7,2" : @"iPhone 6",
@"iPhone8,1" : @"iPhone 6S",
@"iPhone8,2" : @"iPhone 6S Plus",
@"iPhone8,4" : @"iPhone SE",
@"iPhone9,1" : @"iPhone 7",
@"iPhone9,3" : @"iPhone 7",
@"iPhone9,2" : @"iPhone 7 Plus",
@"iPhone9,4" : @"iPhone 7 Plus",
};
if (matches[result]) {
return matches[result];
} else {
return result;
}
}
@end
For plus, you have to check zoom too
struct DeviceType
{
static let IS_IPHONE = (UIDevice.current.userInterfaceIdiom == .phone)
static let IS_IPHONE_4_OR_LESS = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let IS_IPHONE_6_7 = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 667.0) && (UIScreen.main.nativeScale >= UIScreen.main.scale)
private static let IS_STANDARD_IPHONE_6P_7P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
private static let IS_ZOOMED_IPHONE_6P_7P = (UIDevice.current.userInterfaceIdiom == .phone) && (ScreenSize.SCREEN_MAX_LENGTH == 667.0) && (UIScreen.main.nativeScale < UIScreen.main.scale)
static let IS_IPHONE_6P_7P = IS_STANDARD_IPHONE_6P_7P || IS_ZOOMED_IPHONE_6P_7P
}