检测设备是否为 iPhone X。

285

我的iOS应用程序使用自定义高度的 UINavigationBar,这导致在新的iPhone X上出现了一些问题。

是否有人已经知道如何以可靠的方式(使用Objective-C编程)检测应用程序是否在iPhone X上运行?

编辑:

当然可以检查屏幕的大小,但我想知道是否有像TARGET_OS_IPHONE这样的“内置”方法来检测iOS...

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    if (screenSize.height == 812)
        NSLog(@"iPhone X");
}

编辑 2:

我不认为我的问题是与链接的那个问题重复的。当然,有方法可以“测量”当前设备的不同属性,并使用结果来决定使用哪个设备。然而,这并不是我问题的真正重点,正如我在第一个编辑中所强调的。

实际问题是:“是否有可能直接检测当前设备是否为 iPhone X(例如通过某些 SDK 功能),还是我必须使用间接测量?”

根据迄今为止给出的答案,我认为答案是“不,没有直接的方法。只能使用测量方法。”


2
是的,正如我在我的编辑中提到的那样,可以检查屏幕大小。然而问题是,是否有“直接”的方法来查询设备类型,而不是“间接”的测量方法... - Andrei Herford
如果您为iPhone X上传默认图像,则会返回812。在那之前,我认为它会返回iPhone 7的尺寸..不确定... - Fahim Parkar
3
作者只想获取设备类型,而不是屏幕分辨率。为什么不直接检查机器名称呢?@lubilis 是正确的。 - Itachi
2
为什么不直接使用安全区域指南,这是苹果推荐的呢? - holex
4
重要提示,未来的开发人员: 不要像当前主流解决方案那样使用屏幕高度来检测,这样做会导致未来设备出现误判;如果UIWindow尚未渲染(如在AppDelegate初始化函数中),则无法正常工作;在横向应用程序中也无法正常工作,并且如果设置了比例,则模拟器可能会失败。永远不要为此类问题使用魔数!您可以像我在这里做的那样检查硬件标志以确保成功:https://dev59.com/h1YO5IYBdhLWcg3wMO1y#51511947 - Albert Renshaw
显示剩余6条评论
39个回答

423

根据您的问题,答案是否定的。目前没有直接的方法。更多信息可以在这里获取:

以及

iPhone X的高度为2436像素

来自设备屏幕大小和分辨率:

输入图像描述

来自设备屏幕大小和方向:

输入图像描述

Swift 3及更高版本:

if UIDevice().userInterfaceIdiom == .phone {
    switch UIScreen.main.nativeBounds.height {
        case 1136:
            print("iPhone 5 or 5S or 5C")
        
        case 1334:
            print("iPhone 6/6S/7/8")
        
        case 1920, 2208:
            print("iPhone 6+/6S+/7+/8+")
        
        case 2436:
            print("iPhone X/XS/11 Pro")
        
        case 2688:
            print("iPhone XS Max/11 Pro Max")
        
        case 1792:
            print("iPhone XR/ 11 ")
        
        default:
            print("Unknown")
        }
    }

Objective-C:

目标-C
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        switch ((int)[[UIScreen mainScreen] nativeBounds].size.height) {
            case 1136:
                printf("iPhone 5 or 5S or 5C");
                    break;

            case 1334:
                printf("iPhone 6/6S/7/8");
                break;

            case 1920:
            case 2208:
                printf("iPhone 6+/6S+/7+/8+");
                break;

           case 2436:
                printf("iPhone X/XS/11 Pro");
                 break;

            case 2688:
                printf("iPhone XS Max/11 Pro Max");
                 break;

            case 1792:
                printf("iPhone XR/ 11 ");
                 break;

            default:
                printf("Unknown");
                break;
        }
    }

Xamarin.iOS

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) {
    if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1136) {
        Console.WriteLine("iPhone 5 or 5S or 5C");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1334) {
        Console.WriteLine("iPhone 6/6S/7/8");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1920 || (UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2208) {
        Console.WriteLine("iPhone 6+/6S+/7+/8+");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2436) {
        Console.WriteLine("iPhone X, XS, 11 Pro");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2688) {
        Console.WriteLine("iPhone XS Max, 11 Pro Max");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1792) {
        Console.WriteLine("iPhone XR, 11");
    } else {
        Console.WriteLine("Unknown");
    }
}

根据您的问题,建议使用screenSize.height作为浮点数812.0f而不是整数812

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
        // 812.0 on iPhone X, XS
        // 896.0 on iPhone XS Max, XR.

    if (screenSize.height >= 812.0f)
        NSLog(@"iPhone X");
    }

如需更多信息,请参阅iOS人机界面指南中以下页面:

Swift

使用topNotch进行检测:

如果有人考虑使用刘海来检测iPhoneX,请注意在“横屏”模式下,所有iPhone的刘海都是相同的。

var hasTopNotch: Bool {
    if #available(iOS 13.0,  *) {
        return UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.safeAreaInsets.top ?? 0 > 20
    }else{
     return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
    }

    return false
}

Objective-C

- (BOOL)hasTopNotch {
   if (@available(iOS 13.0, *)) {
       return [self keyWindow].safeAreaInsets.top > 20.0;
   }else{
       return [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0;
   }
   return  NO;
}

- (UIWindow*)keyWindow {
    UIWindow        *foundWindow = nil;
    NSArray         *windows = [[UIApplication sharedApplication]windows];
    for (UIWindow   *window in windows) {
        if (window.isKeyWindow) {
            foundWindow = window;
            break;
        }
    }
    return foundWindow;
}

更新:

不要使用userInterfaceIdiom属性来识别设备类型,因为userInterfaceIdiom文档中解释道:

对于通用应用程序,您可以使用此属性针对特定类型的设备调整应用程序的行为。例如,iPhone和iPad设备具有不同的屏幕尺寸,因此您可能希望基于当前设备的类型创建不同的视图和控件。

也就是说,该属性仅用于标识运行中的应用程序的视图样式。但是,iPhone应用程序(而不是通用应用程序)可以通过App Store安装在iPad设备上,在这种情况下,userInterfaceIdiom也将返回UIUserInterfaceIdiomPhone

正确的方法是通过uname获取机器名称。详情请参考以下内容:


1
@Medhi - iPhone X 的分辨率为1125 x 2436像素(~458 ppi像素密度)。 - Anbu.Karthik
16
不!iPhone应用程序(而不是宇宙)可以通过App Store安装在iPad设备上,此时userInterfaceIdiom也将返回UIUserInterfaceIdiomPhone。这个答案是错误的。 - Itachi
@Itachi - 我同意你的观点,能否根据你的评论更新答案,这对许多用户很有用。 - Anbu.Karthik
1
@ThreeCoins,请根据Leo Dabus的建议更新您关于Plus设备的答案。它在Plus模拟器上可以工作,但在设备上无法工作。 - Hiren Gujarati
2
这是不好的,因为它可能会导致未来设备出现误报; 如果UIWindow尚未呈现(AppDelegate),则无法工作;在横向应用程序中无法工作,并且如果设置了比例,则模拟器可能会失败。您可以像我在这里所做的那样检查硬件标志以确保成功:https://dev59.com/h1YO5IYBdhLWcg3wMO1y#51511947 - Albert Renshaw
显示剩余29条评论

108

另一种可能性是,它适用于iOS 11和iOS 12,因为iPhone X是唯一在顶部有凹口并且内嵌44的手机。这就是我在这里真正检测到的内容:

Objective-C:

    BOOL iPhoneX = NO;
    if (@available(iOS 11.0, *)) {
        UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
        if (mainWindow.safeAreaInsets.top > 24.0) {
            iPhoneX = YES;
        }
    }

Swift 4:

/// Has safe area
///
/// with notch: 44.0 on iPhone X, XS, XS Max, XR.
///
/// without notch: 20.0 on iPhone 8 on iOS 12+.
///
static var hasSafeArea: Bool {
    guard #available(iOS 11.0, *), let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top, topPadding > 24 else {
        return false
    }
    return true
}

当然,如果您处于横屏方向,您可能需要检查左右安全区域插图。

编辑:_window是AppDelegate的UIWindow,在应用程序didFinishLaunchingWithOptions中执行此检查。

更新iOS 12的答案以检查top > 24而不是top > 0。

编辑:在模拟器中,您可以转到Hardware,切换呼叫状态栏。这样做会显示我,在iPhone X上的iOS 11或iPhone XS iOS 12中,当进行通话时状态栏高度不会改变。在两种情况下,唯一变化的是时间图标,其会获得绿色背景。这是一个快照:

输入图片描述


5
安全区域插图将包含其他设备上状态栏的高度,如果可见的话。检查这是否为0只能告诉您状态栏是否可见,而不能告诉您设备是否为iPhone X。 - IMcD23
3
库克表示:“这可能在 iPhone Xs 或 iPhone 11 上出现问题。” - Itachi
11
我稍微改了一下,现在使用 if _window.safeAreaInsets != UIEdgeInsets.zero 来适应任何设备旋转方向。 - Fraser
2
如果您不想使用.top,则在iPhone X上,safeAreaInsets.bottom将为34,在其他设备上为0。 - blwinters
7
警告:不要使用此代码,它无法在 iOS 12 上正常运行。同时也没有文档说明 UIWindow 在这种情况下应该做什么。http://openradar.appspot.com/42372793 - steipete
显示剩余6条评论

80

根据实际需要,您应执行iPhone X的不同检测。

用于处理顶部缺口 (状态栏、导航栏) 等。

class var hasTopNotch: Bool {
    if #available(iOS 11.0, tvOS 11.0, *) {
        // with notch: 44.0 on iPhone X, XS, XS Max, XR.
        // without notch: 24.0 on iPad Pro 12.9" 3rd generation, 20.0 on iPhone 8 on iOS 12+.
        return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 24
    }
    return false
}

处理底部 home 指示器(tabbar)等问题的方法。

class var hasBottomSafeAreaInsets: Bool {
    if #available(iOS 11.0, tvOS 11.0, *) {
        // with home indicator: 34.0 on iPhone X, XS, XS Max, XR.
        // with home indicator: 20.0 on iPad Pro 12.9" 3rd generation.
        return UIApplication.shared.delegate?.window??.safeAreaInsets.bottom ?? 0 > 0
    }
    return false
}

用于背景大小、全屏功能等。

class var isIphoneXOrBigger: Bool {
    // 812.0 on iPhone X, XS.
    // 896.0 on iPhone XS Max, XR.
    return UIScreen.main.bounds.height >= 812
}

注意:最终将其与UIDevice.current.userInterfaceIdiom == .phone混合使用
注意:此方法需要有LaunchScreen故事板或适当的LaunchImages。

用于背景比例、滚动特性等方面的处理。

class var isIphoneXOrLonger: Bool {
    // 812.0 / 375.0 on iPhone X, XS.
    // 896.0 / 414.0 on iPhone XS Max, XR.
    return UIScreen.main.bounds.height / UIScreen.main.bounds.width >= 896.0 / 414.0
}

注意:此方法需要具有LaunchScreen storyboard或适当的LaunchImages。

用于分析、统计、跟踪等。

获取机器标识符并将其与文档中的值进行比较:

class var isIphoneX: Bool {
    var size = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    var machine = [CChar](repeating: 0, count: size)
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    let model = String(cString: machine)
    return model == "iPhone10,3" || model == "iPhone10,6"
}

要将模拟器作为有效的 iPhone X 纳入您的分析中:

class var isIphoneX: Bool {
    let model: String
    if TARGET_OS_SIMULATOR != 0 {
        model = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
    } else {
        var size = 0
        sysctlbyname("hw.machine", nil, &size, nil, 0)
        var machine = [CChar](repeating: 0, count: size)
        sysctlbyname("hw.machine", &machine, &size, nil, 0)
        model = String(cString: machine)
    }
    return model == "iPhone10,3" || model == "iPhone10,6"
}

要包括 iPhone XS、XS Max 和 XR,只需寻找以 "iPhone11," 开头的型号:

return model == "iPhone10,3" || model == "iPhone10,6" || model.starts(with: "iPhone11,")

为支持面部 ID

import LocalAuthentication
/// will fail if user denies canEvaluatePolicy(_:error:)
class var canUseFaceID: Bool {
    if #available(iOS 11.0, *) {
        return LAContext().biometryType == .typeFaceID
    }
    return false
}

我原本希望 return LAContext().biometryType == .typeFaceID 可以在用户拒绝 canEvaluatePolicy 的情况下工作,但是它对我来说并不起作用,它仍然返回 .none - Jeremy
嗯,@Jeremy,这是一种记录下来的行为,是苹果隐私政策的后果。这就是为什么方法上面有注释的原因。 - Cœur
啊,我误解了你的评论。我以为你的意思是使用canEvaluatePolicy可能会失败,所以改用以下方法。我觉得有点奇怪,直到用户响应切换之前,你可以检查设备是否具有面容ID,然后你甚至不能再检查了。我该如何提供有用的错误消息,告诉用户去设置中切换面容ID呢? - Jeremy
苹果是否限制了对LAContextsysctlbyname的调用?我的意思是,如果我们使用这些方法,苹果会拒绝应用程序吗? - Mateo Olaya
1
@MateoOlaya 我的回答中没有任何苹果公司会拒绝的内容:你可以全部使用。 - Cœur
显示剩余2条评论

43

您可以按尺寸检测iPhone X设备,实现方法如下:

Swift

if UIDevice().userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436 {
   //iPhone X
}

Objective-C

if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone && UIScreen.mainScreen.nativeBounds.size.height == 2436)  {
  //iPhone X     
}

输入图像描述

但是,

这种方法不够充分。如果苹果公司宣布推出与 iPhone X 同样尺寸的新款 iPhone,那么最好的方法是使用硬件字符串来检测设备。

对于较新的设备,硬件字符串如下所示。

iPhone 8 - iPhone10,1iPhone 10,4

iPhone 8 Plus - iPhone10,2iPhone 10,5

iPhone X - iPhone10,3iPhone10,6


2
你应该使用[UIDevice currentDevice]而不是[[UIDevice alloc] init] - S. Matsepura
硬件字符串的唯一问题就是它无法在模拟器上运行。 - quemeful

43

请查看设备型号/机器名称,不要直接在代码中使用点/像素计数,这是硬编码,对设备硬件没有意义,设备型号是匹配设备类型的唯一标识符

#import <sys/utsname.h>

NSString* deviceName()
{
    struct utsname systemInfo;
    uname(&systemInfo);

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

结果:

@"iPhone10,3" on iPhone X (CDMA)
@"iPhone10,6" on iPhone X (GSM)

请参考这个答案

完整代码实现:

#import <sys/utsname.h>

NSString * GetDeviceModel(void)
{
    static dispatch_once_t onceToken;
    static NSString *strModelID = nil;

    dispatch_once(&onceToken, ^{
#if TARGET_IPHONE_SIMULATOR
        strModelID = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];
#else
        struct utsname systemInfo;

        uname(&systemInfo);
        strModelID = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
#endif
    });

    return strModelID;
}

// See the `Hardware strings` in https://en.wikipedia.org/wiki/List_of_iOS_devices
BOOL IsiPhoneX(void)
{
    NSString *strModelID = GetDeviceModel();

    return [strModelID isEqualToString:@"iPhone10,3"] || [strModelID isEqualToString:@"iPhone10,6"];
}

BOOL IsNotchiPhone(void)
{
    NSArray<NSString *> *notchiModels = @[
        @"iPhone10,3", @"iPhone10,6", // iPhone X
        @"iPhone11,2", @"iPhone11,4", @"iPhone11,6", // iPhone XS (Max)
        @"iPhone11,8", // iPhone XR
        @"iPhone12,1", @"iPhone12,3", @"iPhone12,5", // iPhone 11 (Pro (Max))
        @"iPhone13,1", @"iPhone13,2", @"iPhone13,3", @"iPhone13,4", // iPhone 12 ([mini]|[Pro (Max)])
    ];

    return [notchiModels containsObject:GetDeviceModel()];
}

1
非常好的答案,因为它正确地处理了模拟器。请在“完整代码”部分添加#import行。我在第一次尝试时错过了它(复制/粘贴)。 - mpoisot
1
请参考**此维基**以获取设备型号字符串的完整列表。顺便说一句,@"iphone10,3"也可以被视为硬编码。 - YvesLeBorg
1
@YvesLeBorg 是的,这确实是一个非常关键和有争议的问题。硬件模型字符串具有设备的唯一标识符,而不是屏幕点数。通常,它用于数据统计。 - Itachi

26

看完所有答案后,我最终采用了以下解决方案:

解决方案(适用于Swift 4.1)

extension UIDevice {
    static var isIphoneX: Bool {
        var modelIdentifier = ""
        if isSimulator {
            modelIdentifier = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
        } else {
            var size = 0
            sysctlbyname("hw.machine", nil, &size, nil, 0)
            var machine = [CChar](repeating: 0, count: size)
            sysctlbyname("hw.machine", &machine, &size, nil, 0)
            modelIdentifier = String(cString: machine)
        }

        return modelIdentifier == "iPhone10,3" || modelIdentifier == "iPhone10,6"
    }

    static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0
    }
}

使用

if UIDevice.isIphoneX {
    // is iPhoneX
} else {
    // is not iPhoneX
}

注意

在Swift 4.1之前,您可以通过以下方式检查应用程序是否在模拟器上运行:

TARGET_OS_SIMULATOR != 0

从Swift 4.1开始,您可以使用目标环境平台条件检查应用程序是否在模拟器上运行:

#if targetEnvironment(simulator)
    return true
#else
    return false
#endif

(旧方法仍然有效,但这种新方法更具未来性)


苹果公司会对此满意吗? - Surjeet Rajput
@commando24 是的,我不认为他们会因为这段代码而拒绝该应用程序。 - Cloud9999Strife

26
#define IS_IPHONE        (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_4      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0)
#define IS_IPHONE_5      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6PLUS  (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_IPHONE_X      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)

定义IS_IPHONE_X为(IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)

#define IS_IPHONE_XS      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)
#define IS_IPHONE_X_MAX      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 896.0)
#define IS_RETINA        ([[UIScreen mainScreen] scale] >= 2.0) // 3.0 for iPhone X, 2.0 for others

#define IS_IPAD_DEVICE   [(NSString*)[UIDevice currentDevice].model hasPrefix:@"iPad"]

注意:请小心,此功能仅适用于纵向方向


2
请注意,它仅适用于纵向(竖屏)方向。 - CFIFok
1
谢谢这个。运行良好。在横屏模式下,您需要调整那些数字。iPhoneX在横屏模式下的魔术数字是375.0。 - pvella
有一些使用nativeScale3.0的iPhone Plus/Max/Pro,对吧? - Itachi

18

所有基于尺寸的答案都容易在未来的设备上出现错误行为。它们今天可以工作,但如果明年出现一个尺寸相同但摄像头等功能被放到玻璃下面没有“刘海”的iPhone怎么办?如果唯一的选择是更新应用程序,那么对你和你的客户来说,这是一个糟糕的解决方案。

你也可以检查硬件型号字符串,比如“iPhone10,1”,但这是有问题的,因为有时苹果会针对全球不同的运营商发布不同的型号号码。

正确的方法是重新设计顶部布局,或者解决你正在遇到的自定义导航栏高度问题(这是我要专注的)。但是,如果你决定不做任何一个方案,请意识到你所做的任何事情都是为了让它在今天起作用而进行的某种妥协,而且你需要在某个时候进行修正,可能需要多次修正才能使此类妥协持续发挥作用。


1
正确。将一个假设数字X始终为A的假设细化为除非条件Y,否则数字X始终为A,这只是更深入地挖掘。基于由苹果提名的安全区域确定大小,而不是凭空猜测。 - Tommy
2
当下我只关心我的应用程序能否在今天正常运行,至于下一代iPhone何时发布,那是以后的事情。 - Vahid Amiri

16

支持iPhone 12的SWIFT 4/5可重复使用扩展

    extension UIDevice {
    
    enum `Type` {
        case iPhone_5_5S_5C_SE1
        case iPhone_6_6S_7_8_SE2
        case iPhone_6_6S_7_8_PLUS
        case iPhone_X_XS_12mini
        case iPhone_XR_11
        case iPhone_XS_11Pro_Max
        case iPhone_12_Pro
        case iPhone_12_Pro_Max
    }
    
    var hasHomeButton: Bool {
        switch type {
        case . iPhone_X_XS_12mini, . iPhone_XR_11, .iPhone_XS_11Pro_Max, . iPhone_XS_11Pro_Max, .iPhone_12_Pro, .iPhone_12_Pro_Max:
            return false
        default:
            return true
        }
    }
    
    var type: Type {
        if UI_USER_INTERFACE_IDIOM() == .phone {
        switch UIScreen.main.nativeBounds.height {
        case 1136:
            return .iPhone_5_5S_5C_SE1
        case 1334:
            return .iPhone_6_6S_7_8_SE2
        case 1920, 2208:
            return .iPhone_6_6S_7_8_PLUS
        case 2436:
            return .iPhone_X_XS_12mini
        case 2532:
            return .iPhone_12_Pro
        case 2688:
            return .iPhone_XS_11Pro_Max
        case 2778:
            return .iPhone_12_Pro_Max
        case 1792:
            return .iPhone_XR_11
        default:
            assertionFailure("Unknown phone device detected!")
            return .iPhone_6_6S_7_8_SE2
        }
    } else {
        assertionFailure("Unknown idiom device detected!")
        return .iPhone_6_6S_7_8_SE2
    }
   }
}

2
好的扩展,但最有用的是UIDevice.current.hasHomeButton - WINSergey
1
@ale_stro,使用userInterfaceIdiom来确定通用应用程序的设备好吗?大多数人不建议这样做。使用它会有什么危害吗? - shaqir saiyed

15

SWIFT 4+答案

iPhone X,XR,XS,XSMAX,11 Pro,11 Pro Max:

注意:需要真实设备进行测试

参考

 let deviceType = UIDevice.current.modelName
        switch deviceType {
        case "iPhone10,3", "iPhone10,6":
            print("iPhoneX")
        case "iPhone11,2":
            print("iPhone XS")
        case "iPhone11,4":
            print("iPhone XS Max")
        case "iPhone11,6":
            print("iPhone XS Max China")
        case "iPhone11,8":
            print("iPhone XR")
        case "iPhone12,3":
            print("iPhone 11 Pro")
        case "iPhone12,5":
            print("iPhone 11 Pro Max")
        default:
            break
}

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)))
        }
        return identifier
    }
}

对于方法1,您可以将“var window”属性移出func,并在其中仅使用“let”常量(类型为UIWindow,即非可选项)。我喜欢这个答案,因为在启动时,self.view.window可能为空,而UIApplication.shared.keyWindow也可能为空,而以这种方式创建UIWindow每次都能正常工作。 - Rolleric
这里的每个人都使用设备屏幕高度作为决定因素。苹果公司可以轻松地发布另一款相同尺寸的设备(他们在随后的一年中推出了iPhone XS)。这将从UNIX中获取实际设备型号。 - Xaxxus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接