在上一条小集《iPhone 屏幕分辨率终极指南》中,我们整理介绍了目前已发布的所有 iPhone 设备的屏幕数据,包括了最新上市的 iPhone XS、iPhone XS Max 和 iPhone XR。
最后我们介绍了一种在代码中通过获取屏幕的高度判断是否等于 812.0
或 896.0
来检测设备是否为 iPhone X 的方法,但该方法存在小瑕疵,需要考虑一下两点:
- 当 App 支持横竖屏切换时,在横屏模式下也能够正确判断;
- 在模拟器中调试时,能够正确判断当前所选则的模拟器类型是不是 iPhone X;
因此,本条小集重新整理一下我们目前所了解到的几种检测设备是否为 iPhone X 的方式,供大家参考,不足之处欢迎补充。
备注:这里所说的 iPhone X 泛指屏幕大小为 5.8、6.1、6.5 英寸三种尺寸,且带有顶部刘海和底部操作条的 iPhone 设备。
方式一:通过获取设备的 device model 来判断
每一台 iOS 设备都有对应的硬件编码/标识符,称为 device model
或者叫 machine name
,我们可以通过如下两种方法来获取 device model/machine name。
1 |
|
例如,去年发布的第一代 iPhone X 对应的 device mode 为 iPhone10,3
和 iPhone10,6
,而今年最新发布 iPhone XS 对应 iPhone11,2
,iPhone XS Max 对应 iPhone11,4
和 iPhone11,6
,iPhone XR 对应 iPhone11,8
,完整的 device mode 数据参考这里:
不过需要注意的是,上述两种获取 device model 的方法在模拟器中运行得到的值为 i386
或 x86_64
,因此在模拟器中我们可以通过如下方式正确获取模拟器所对应的 device model:
1 | // 获取模拟器所对应的 device model |
综上,我们可以通过判断 device model 是否为 “iPhone10,3” 和 “iPhone10,6” 或者以 “iPhone11,”(新设备)开头,来检测设备是否为 iPhone X,完整代码如下:
1 | + (BOOL)isiPhoneX { |
方式二:通过获取屏幕的宽高来判断
正如我们前一条小集讲到,目前 iPhone X 设备的屏幕宽高对应的开发尺寸只有两种,分别为 375pt * 812pt
和 414pt * 896pt
,因此我们可以根据屏幕的高度来判断设备是否为 iPhone X。但是此时需要考虑设备处于横屏或者竖屏的情况,这两种情况的宽高刚好是相反的(当然,如果你的 App 不用支持横屏的情况,就相对比较简单了)。
在 UIDevice
中提供了一个 orientation
属性用于获取设备的方向(横向、竖向、或者水平),一开始我们想着先通过这个属性判断设备处于横屏或者竖屏,然后分别取其对应的屏幕宽度(横屏下)或者高度(竖屏下)来判断,但是当这个属性的值为 FaceUp
或者 FaceDown
(即设备放在水平面上),我们是无法知道此时设备是处于横屏还是竖屏的。
后面我们想了一个简便的方法,即获取屏幕的宽度和高度,取较大一方进行比较是等于 812.0
或 896.0
,代码如下:
1 | + (BOOL)isiPhoneX { |
方式三:通过底部安全区域的高度来判断
在去年 iPhone X 发布后,为了适配顶部的浏览和底部的操作条,苹果在 iOS 11 上引入安全区域概念,建议开发者在安全区域内进行 UI 布局,因此我们可以获取屏幕 keyWindow 的 safeAreaInsets
值来判断设备是否 iPhone X。
iPhone X 在竖屏下,keyWindow 的 safeAreaInsets
值为:1
{top: 44, left: 0, bottom: 34, right: 0}
而在横屏下,其值为:1
{top: 0, left: 44, bottom: 21, right: 44}
因此,我们可以比较 safeAreaInsets
的 bottom
是否等于 34.0
或者 21.0
来判断设备是否为 iPhone X,因为其他设备对应的 bottom
横竖屏下都为 0
,代码如下:
1 | + (BOOL)isiPhoneX { |
不过该方式有个不足是,必须在 AppDelegate 的 didFinishLaunchingWithOptions
回调中等 keyWindow 初始化之后才能正确判断。
方式四:通过是否支持 FaceID 判断
由于目前只有 iPhone X 设备支持 FaceID,因此我们也可以通过判断设备是否支持 FaceID 来判断,代码如下:
1 | + (BOOL)canUseFaceID { |
不足:如果用户禁用 canEvaluatePolicy:error:
方法的使用将无法正确判断,而且在也不适用于模拟器中的判断。
方式五:通过 UIStatusBar 的高度判断
在 iPhone X 之前,所有 iPhone 设备的 StatusBar(状态栏)高度都为 20pt
,而 iPhone X 的为 44pt
,因此我们可以通过获取状态栏的高度判断是否等于 44.0
来检测设备是否为 iPhone X,代码如下:
1 | + (BOOL)isiPhoneX { |
不足:该方法只适用于竖屏且显示状态栏的情况下才能正确检测,而在横屏模式下,或者 App 隐藏导航栏时,获取到的状态栏高度都为 0
(statusBarFrame
的值为 CGRectZero
),就无法判断了。
你是否有其他判断方式呢?欢迎补充~
结语
最后,绝大部分场景,我们需要检测设备是否为 iPhone X 是为了适配顶部的刘海区域和底部的操作条区域,但是这里我们更推荐通过 Auto Layout 结合 Safe Area 进行 UI 布局,以适应越来越复杂的屏幕状况。