检测设备是否为iPhone X.

And*_*ord 248 iphone objective-c ios iphone-x

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

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

编辑:

当然,检查屏幕的大小是可能的,但是,我想知道是否有一些"内置"方法,如TARGET_OS_IPHONE检测iOS ...

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

编辑2:

我不认为,我的问题是链接问题的重复.当然,有一些方法可以"测量"当前设备的不同属性,并使用结果来决定使用哪个设备.然而,这不是我的问题的实际问题,因为我在第一次编辑时试图强调.

实际的问题是:"是否可以直接检测当前设备是否是iPhone X(例如,通过某些SDK功能)或者我是否必须使用间接测量"

到目前为止给出的答案,我认为答案是"不,没有直接的方法.测量是要走的路".

Anb*_*hik 359

根据你的问题,答案是否定的.没有直接的方法.有关更多信息,您可以在此处获取信息:

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")
        }
    }
Run Code Online (Sandbox Code Playgroud)

Objective-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, 2208:
            printf("iPhone 6+/6S+/7+/8+");
            break;

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

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

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

        default:
            printf("Unknown");
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

根据您的问题如下:

或者使用screenSize.heightfloat 812.0f 而不是int 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");
    }
Run Code Online (Sandbox Code Playgroud)

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

斯威夫特:

检测topNotch:

var hasTopNotch: Bool {
    if #available(iOS 11.0,  *) {
        return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
    }

    return false
}
Run Code Online (Sandbox Code Playgroud)

Objective-C:

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

    return  NO;
}
Run Code Online (Sandbox Code Playgroud)

更新:

请勿使用该userInterfaceIdiom属性来标识设备类型,因为userInterfaceIdiom文档说明:

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

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

正确的方法是通过获取机器名称uname.请查看以下详细信息:

  • ***NO!***iPhone应用程序(不是宇宙)可以通过App store安装在iPad设备上,在这种情况下,`userInterfaceIdiom`也会返回`UIUserInterfaceIdiomPhone`.这个答案是对的. (13认同)
  • 这很不好,因为它可能导致将来的设备出现误报。如果UIWindow尚未渲染(AppDelegate),则将不起作用,无法在横向应用程序中使用,并且如果设置了比例,则可能无法在模拟器上运行。您可以像在这里一样检查硬件标志以确保成功:/sf/answers/3605836321/ (2认同)

sas*_*anb 99

另一种可能性,适用于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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

斯威夫特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
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:_window是AppDelegate的UIWindow,其中此检查在应用程序didFinishLaunchingWithOptions中完成.

为iOS 12更新了答案,检查顶部> 24而不是顶部> 0.

编辑:在模拟器中,您可以转到硬件,切换通话状态栏.这样做表明我在进行通话时iOS 11或iPhone XS iOS 12上的iPhone X上的状态栏高度没有变化.所有这些变化都是时间图标,在两种情况下都会获得绿色背景.这是一个快照:

在此输入图像描述

  • 我已经改编了一下并使用`if _window.safeAreaInsets!= UIEdgeInsets.zero`以允许任何设备方向 (11认同)
  • 警告:不要使用它,它会在iOS 12上中断.在这种情况下,UIWindow也应该没有记录.http://openradar.appspot.com/42372793 (7认同)
  • 安全区域insets将包含状态栏高度(如果可见),在其他设备上.检查此值是否为0只会告诉您状态栏是否可见,而不是设备是否为iPhone X. (5认同)
  • 库克说:"这可能会破坏*iPhone Xs或iPhone 11*". (3认同)
  • 如果您不想使用`.top`,`safeAreaInsets.bottom`在iPhone X上将为34,在其他设备上为0。 (2认同)

Cœu*_*œur 69

您应根据实际需要对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
}
Run Code Online (Sandbox Code Playgroud)

处理底部家庭指标(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
}
Run Code Online (Sandbox Code Playgroud)

用于背景大小,全屏功能等

class var isIphoneXOrBigger: Bool {
    // 812.0 on iPhone X, XS.
    // 896.0 on iPhone XS Max, XR.
    return UIScreen.main.bounds.height >= 812
}
Run Code Online (Sandbox Code Playgroud)

注意:最终将它与UIDevice.current.userInterfaceIdiom == .phone
Note 混合:此方法需要具有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
}
Run Code Online (Sandbox Code Playgroud)

注意:此方法需要具有LaunchScreen故事板或正确的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"
}
Run Code Online (Sandbox Code Playgroud)

要将模拟器作为有效的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"
}
Run Code Online (Sandbox Code Playgroud)

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

return model == "iPhone10,3" || model == "iPhone10,6" || model.starts(with: "iPhone11,")
Run Code Online (Sandbox Code Playgroud)

用于faceID支持

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


Jay*_*eep 42

你可以这样做,根据尺寸检测iPhone X设备.

迅速

if UIDevice().userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436 {
   //iPhone X
}
Run Code Online (Sandbox Code Playgroud)

目标 - C.

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

在此输入图像描述

但是,

这还不够.如果Apple宣布下一代iPhone具有相同尺寸的iPhone X,那么最好的方法是使用硬件字符串来检测设备.

对于较新的设备硬件字符串如下.

iPhone 8 - iPhone10,1iPhone 10,4

iPhone 8 Plus - iPhone10,2iPhone 10,5

iPhone X - iPhone10,3iPhone10,6

  • 你应该使用 `[UIDevice currentDevice]` 而不是 `[[UIDevice alloc] init]` (2认同)

Ita*_*chi 37

检查设备型号/机器名称,不要直接使用代码中的点/像素数,它是硬代码,对设备硬件毫无意义.

#import <sys/utsname.h>

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

    return [NSString stringWithCString:systemInfo.machine
                          encoding:NSUTF8StringEncoding];
}
Run Code Online (Sandbox Code Playgroud)

结果:

@"iPhone10,3" on iPhone X (CDMA)
@"iPhone10,6" on iPhone X (GSM)
Run Code Online (Sandbox Code Playgroud)

请参阅此答案.

完整的代码实现:

#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)
{
    NSString *strModelID = GetDeviceModel();

    return [strModelID isEqualToString:@"iPhone10,3"] || [strModelID isEqualToString:@"iPhone10,6"] || // iPhone X
           [strModelID isEqualToString:@"iPhone11,2"] || [strModelID isEqualToString:@"iPhone11,4"] || [strModelID isEqualToString:@"iPhone11,6"] || // iPhone XS (Max)
           [strModelID isEqualToString:@"iPhone11,8"] // iPhone XR
           [strModelID isEqualToString:@"iPhone12,1"] || [strModelID isEqualToString:@"iPhone12,3"] || [strModelID isEqualToString:@"iPhone12,5"]; // iPhone 11 (Pro (Max))
}
Run Code Online (Sandbox Code Playgroud)


Jag*_*ngh 25

#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)
Run Code Online (Sandbox Code Playgroud)

定义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"]
Run Code Online (Sandbox Code Playgroud)

注意: - 小心,它仅适用于纵向方向

  • 小心,它仅适用于纵向方向 (2认同)

Clo*_*ife 23

在查看了所有答案后,这就是我最终做的事情:

解决方案(兼容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
    }
}
Run Code Online (Sandbox Code Playgroud)

使用

if UIDevice.isIphoneX {
    // is iPhoneX
} else {
    // is not iPhoneX
}
Run Code Online (Sandbox Code Playgroud)

注意

Pre Swift 4.1您可以检查应用程序是否在模拟器上运行,如下所示:

TARGET_OS_SIMULATOR != 0
Run Code Online (Sandbox Code Playgroud)

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

#if targetEnvironment(simulator)
    return true
#else
    return false
#endif
Run Code Online (Sandbox Code Playgroud)

(较旧的方法仍然有效,但这种新方法更具前瞻性)


cla*_*rus 18

所有这些基于维度的答案都容易受到未来设备上的错误行为的影响.他们今天会工作,但是如果明年有一部iPhone的尺寸相同,但玻璃下面有相机等,那么就没有"缺口"了.如果唯一的选择是更新应用程序,那么对您和您的客户来说,这是一个糟糕的解决方案.

您还可以检查硬件模型字符串,如"iPhone10,1",但这有问题,因为有时Apple会为全球不同的运营商发布不同的型号.

正确的方法是重新设计顶层布局,或者解决自定义导航栏高度所遇到的问题(这就是我所关注的).但是,如果你决定不做这些事情中的任何一件事,那么你应该意识到,无论你做什么都是为了让它今天起作用,你需要在某些时候纠正它,也许是多次,以保持黑客攻击工作.

  • 当它真的出现在那里时,我会担心下一款iPhone.我希望我的应用程序能够在今天工作. (2认同)

Jac*_*ack 12

SWIFT 4+答案

iPhone X,XR,XS,XSMAX:

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

参考

 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")
        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
    }
}
Run Code Online (Sandbox Code Playgroud)


Hen*_*rik 10

对的,这是可能的.下载UIDevice-Hardware扩展(或通过CocoaPod'UIDevice-Hardware'安装),然后使用:

NSString* modelID = [[[UIDevice currentDevice] modelIdentifier];
BOOL isIphoneX = [modelID isEqualToString:@"iPhone10,3"] || [modelID isEqualToString:@"iPhone10,6"];
Run Code Online (Sandbox Code Playgroud)

请注意,这在模拟器中不起作用,仅在实际设备上有效.


ale*_*tro 10

SWIFT 4可重复使用的扩展

    public extension UIDevice {

    public enum `Type` {
        case iPad
        case iPhone_unknown
        case iPhone_5_5S_5C
        case iPhone_6_6S_7_8
        case iPhone_6_6S_7_8_PLUS
        case iPhone_X_Xs
        case iPhone_Xs_11_Pro_Max
        case iPhone_Xr_11
        case iPhone_11_Pro
    }

    public var hasHomeButton: Bool {
        switch type {
        case .iPhone_X_Xs, .iPhone_Xr_11, .iPhone_Xs_11_Pro_Max, .iPhone_11_Pro:
            return false
        default:
            return true
        }
    }

    public var type: Type {
        if userInterfaceIdiom == .phone {
            switch UIScreen.main.nativeBounds.height {
            case 1136: return .iPhone_5_5S_5C
            case 1334: return .iPhone_6_6S_7_8
            case 1920, 2208: return .iPhone_6_6S_7_8_PLUS
            case 2436: return .iPhone_X_Xs
            case 2688: return .iPhone_Xs_11_Pro_Max
            case 1792: return .iPhone_Xr_11
            case 2426: return .iPhone_11_Pro
            default: return .iPhone_unknown
        }
        }
        return .iPad
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的扩展,但是这里最有用的是`UIDevice.current.hasHomeButton` (2认同)

Mat*_*tOZ 9

根据@ saswanb的回复,这是一个Swift 4版本:

var iphoneX = false
if #available(iOS 11.0, *) {
    if ((UIApplication.shared.keyWindow?.safeAreaInsets.top)! > CGFloat(0.0)) {
        iphoneX = true
    }
}
Run Code Online (Sandbox Code Playgroud)


bud*_*ino 7

我知道这只是一个Swift解决方案,但它可以帮助某人.

globals.swift在每个项目中都有一个我总是添加的东西是DeviceType轻松检测用户的设备:

struct ScreenSize {
  static let width = UIScreen.main.bounds.size.width
  static let height = UIScreen.main.bounds.size.height
  static let frame = CGRect(x: 0, y: 0, width: ScreenSize.width, height: ScreenSize.height)
  static let maxWH = max(ScreenSize.width, ScreenSize.height)
}

struct DeviceType {
  static let iPhone4orLess = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH < 568.0
  static let iPhone5orSE   = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 568.0
  static let iPhone678     = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 667.0
  static let iPhone678p    = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 736.0
  static let iPhoneX       = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 812.0
  static let iPhoneXRMax   = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxWH == 896.0
  static var hasNotch: Bool {
    return iPhoneX || iPhoneXRMax
  }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

if DeviceType.hasNotch {
  print("This executes on all phones with a notch")
}

if DeviceType.iPhone678 {
  print("This executes on iPhones 6, 7 and 8")
}
Run Code Online (Sandbox Code Playgroud)

如果您LaunchImage在项目中使用,请确保为所有支持的设备(如XS Max,XR)添加图像,因为UIScreen.main.bounds没有这些设备将无法返回正确的值.


Dev*_*ist 5

height由于一个原因,所有使用它的答案只是故事的一半.如果您要在设备方向检查时检查,landscapeLeft或者landscapeRight检查将失败,因为它与... height交换width.

这就是为什么我的解决方案在Swift 4.0中看起来像这样:

extension UIScreen {
    ///
    static var isPhoneX: Bool {
        let screenSize = UIScreen.main.bounds.size
        let width = screenSize.width
        let height = screenSize.height
        return min(width, height) == 375 && max(width, height) == 812
    }
}
Run Code Online (Sandbox Code Playgroud)


Alb*_*haw 5

不要像其他解决方案建议的那样使用屏幕像素大小,这很糟糕,因为它可能导致未来设备误报;如果 UIWindow 尚未呈现(AppDelegate),则无法工作,无法在横向应用程序中工作,并且如果设置了比例,则可能在模拟器上失败。

相反,我为此目的制作了一个宏,它非常易于使用并且依靠硬件标志来防止上述问题。

编辑:更新为支持 iPhoneX、iPhone XS、iPhoneXR、iPhoneXS Max


使用:

if (IS_DEVICE_IPHONEX) {
    //do stuff
}
Run Code Online (Sandbox Code Playgroud)

是的,真的。


宏:

只需将其复制粘贴到任何地方,我更喜欢 .h 文件的最底部 @end

#import <sys/utsname.h>

#if TARGET_IPHONE_SIMULATOR
#define IS_SIMULATOR YES
#else
#define IS_SIMULATOR NO
#endif

#define IS_DEVICE_IPHONEX (\
(^BOOL (void){\
NSString *__modelIdentifier;\
if (IS_SIMULATOR) {\
__modelIdentifier = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"];\
} else {\
struct utsname __systemInfo;\
uname(&__systemInfo);\
__modelIdentifier = [NSString stringWithCString:__systemInfo.machine encoding:NSUTF8StringEncoding];\
}\
NSString *__iPhoneX_GSM_Identifier = @"iPhone10,6";\
NSString *__iPhoneX_CDMA_Identifier = @"iPhone10,3";\
NSString *__iPhoneXR_Identifier = @"iPhone11,8";\
NSString *__iPhoneXS_Identifier = @"iPhone11,2";\
NSString *__iPhoneXSMax_China_Identifier = @"iPhone11,6";\
NSString *__iPhoneXSMax_Other_Identifier = @"iPhone11,4";\
return ([__modelIdentifier isEqualToString:__iPhoneX_GSM_Identifier] || [__modelIdentifier isEqualToString:__iPhoneX_CDMA_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXR_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXS_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXSMax_China_Identifier] || [__modelIdentifier isEqualToString:__iPhoneXSMax_Other_Identifier]);\
})()\
)
Run Code Online (Sandbox Code Playgroud)


Lan*_*ria 5

仅在纵向中,我使用视图框架的宽度和高度来检查:

override func viewDidLoad() {
    super.viewDidLoad()

    // iPhone Xr: -414 x 896
    // iPhone Xs Max: -414 x 896
    // iPhone X, Xs: -375 x 812

    if view.frame.width == 414 && view.frame.height == 896 || view.frame.width == 375 && view.frame.height == 812  {

        print("iPhone X")
    } else {

        print("not iPhone X")
    }

}
Run Code Online (Sandbox Code Playgroud)

此处列出了纵向屏幕尺寸

在此输入图像描述

更新

这个答案已经过时了,现在 iPhone 系列中有更多的 X 系列,你要么必须在里面列出所有这些尺寸if-else,要么检查设备是否有凹口会更容易。大约 1.5 年前,我从 SO 上的某个地方得到了这个答案/代码。如果我可以链接到代码,我会的。

// 1. add an extension to UIDevice with this computed property
extension UIDevice {
    
    var hasTopNotch: Bool {
        if #available(iOS 11.0, tvOS 11.0, *) {
            return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
        }
        return false
    }
} 

// 2. to use in any class
override func viewDidLoad() {
    super.viewDidLoad()

    if UIDevice.current.hasTopNotch {

        print("X series")

    } else {

        print("regular phone")
    }
}
Run Code Online (Sandbox Code Playgroud)