我的iOS应用程序使用 UINavigationBar
的自定义高度,这会导致新的iPhone X出现一些问题 .
如果应用程序在iPhone X上运行,是否有人已经知道如何以编程方式(在Objective-C中)检测 reliable ?
EDIT:
当然可以检查屏幕的大小,但是,我想知道是否有像 TARGET_OS_IPHONE
这样的"build in"方法来检测iOS ...
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if (screenSize.height == 812)
NSLog(@"iPhone X");
}
EDIT 2:
我不认为,我的问题是链接问题的重复 . 当然,有一些方法可以“测量”当前设备的不同属性,并使用结果来决定使用哪个设备 . 然而,这不是我的问题的实际问题,因为我在第一次编辑时试图强调 .
实际问题是: "Is it possible to directly detect if the current device is an iPhone X (e.g. by some SDK feature) or do I have to use indirect measurements" ?
到目前为止给出的答案,我认为答案是“不,没有直接的方法 . 测量是要走的路” .
30 回答
根据你的问题,答案是否定的 . 没有直接的方法 . 有关更多信息,您可以在此处获取信息:
和
iPhone X的高度为2436像素
来自Device Screen Sizes and resolutions:
来自Device Screen Sizes and Orientations:
Swift 3 and later :
Objective-C :
Xamarin.iOS :
根据您的问题如下:
或者使用
screenSize.height
作为float812.0f
not int812
.有关更多信息,请参阅iOS人机界面指南中的以下页面:
Swift :
检测
topNotch
:Objective-C :
UPDATE :
不要使用
userInterfaceIdiom
属性来标识设备类型,因为documentation for userInterfaceIdiom解释说:也就是说,此属性仅用于标识正在运行的应用程序的视图样式 . 但是,iPhone应用程序(不是通用)可以通过App Store安装在iPad设备上,在这种情况下,
userInterfaceIdiom
也会返回UIUserInterfaceIdiomPhone
.正确的方法是通过
uname
获取机器名称 . 请查看以下详细信息:另一种可能性,适用于iOS 11和iOS 12,因为iPhone X是唯一一个在顶部有一个缺口并且插入44的插件 . 这就是我在这里真正检测到的:
Objective-C:
Swift 4:
当然,如果您处于横向方向,则可能需要检查左右安全区域插图 .
编辑:_window是AppDelegate的UIWindow,其中此检查在应用程序didFinishLaunchingWithOptions中完成 .
Answer updated for iOS 12 to check if top > 24 rather than top > 0.
编辑:在模拟器中,您可以转到硬件,切换通话状态栏 . 这样做表明我在进行通话时iOS 11或iPhone XS iOS 12上的iPhone X上的状态栏高度没有变化 . 所有这些变化都是时间图标,在两种情况下都会获得绿色背景 . 这是一个快照:
您应根据实际需要对iPhone X执行不同的检测 .
用于处理顶级(状态栏,导航栏)等 .
用于处理底部主页指示符(tabbar)等 .
用于背景大小,全屏功能等
注意:最终将它与
UIDevice.current.userInterfaceIdiom == .phone
混合注意:此方法需要具有LaunchScreen故事板或正确的LaunchImages
用于背景比例,滚动功能等
注意:此方法需要具有LaunchScreen故事板或正确的LaunchImages
用于分析,统计,跟踪等
获取机器标识符并将其与记录的值进行比较:
要将模拟器作为有效的iPhone X包含在分析中:
要包含iPhone XS,XS Max和XR,只需查找以“iPhone11”开头的型号:
用于faceID支持
您可以这样做以根据维度检测 iPhone X 设备 .
Swift
Objective - C
But ,
这还不够 . 如果Apple宣布下一代iPhone具有相同尺寸的iPhone X,那么最好的方法是使用硬件字符串来检测设备 .
对于较新的设备硬件字符串如下 .
iPhone 8 - iPhone10,1 或 iPhone 10,4
iPhone 8 Plus - iPhone10,2 或 iPhone 10,5
iPhone X - iPhone10,3 或 iPhone10,6
查看the device model / machine name,不要直接使用代码中的点/像素数,它是hard code并且对于设备硬件没有意义 .
结果:
请参阅this answer .
Full code implementation:
define IS_IPHONE_X(IS_IPHONE && [[UIScreen mainScreen] bounds] .size.height == 812.0)
注意: - 小心,它仅适用于纵向方向
在查看了所有答案后,这就是我最终做的事情:
解决方案(兼容Swift 4.1)
使用
注意
Pre Swift 4.1您可以检查应用程序是否在模拟器上运行,如下所示:
从Swift 4.1开始,您可以使用Target environment platform condition检查应用程序是否在模拟器上运行:
(旧的方法仍然有效,但这种新方法更具前瞻性)
所有这些基于维度的答案都容易受到未来设备上的错误行为的影响 . 他们今天会工作,但是如果明年有一部iPhone的尺寸相同,但玻璃下面有相机等,那么就没有“缺口”了 . 如果唯一的选择是更新应用程序,那么对您和您的客户来说,这是一个糟糕的解决方案 .
您还可以检查硬件模型字符串,如“iPhone10,1”,但这有问题,因为有时Apple会为全球不同的运营商发布不同的型号 .
正确的方法是重新设计顶层布局,或者解决你所做的事情,这样做是为了让它工作 today ,你需要在某些时候纠正它,也许多次,以保持黑客工作 .
SWIFT 4+ Answer
iPhone X, XR, XS, XSMAX:
注意:需要真正的设备进行测试
Reference
对的,这是可能的 . 下载UIDevice-Hardware extension(或通过CocoaPod 'UIDevice-Hardware'安装),然后使用:
请注意,这在模拟器中不起作用,仅在实际设备上有效 .
根据@ saswanb的回复,这是一个Swift 4版本:
我知道这只是一个解决方案,但它可以帮助某人 .
我在每个项目中都有
globals.swift
,我总是添加的一件事是DeviceType
,以便轻松检测用户的设备:然后使用它:
如果在项目中使用
LaunchImage
,请确保为所有支持的设备(如XS Max,XR)添加图像,因为如果没有这些设备,UIScreen.main.bounds
将无法返回正确的值 .SWIFT 4 可重复使用 extension
由于一个原因,使用
height
的所有答案只是故事的一半 . 如果您要在设备方向为landscapeLeft
或landscapeRight
时进行检查,则检查将失败,因为height
与width
交换出来 .这就是为什么我的解决方案在Swift 4.0中看起来像这样:
您不应该假设Apple发布的唯一具有不同UINavigationBar高度的设备将是iPhone X.尝试使用更通用的解决方案来解决此问题 . 如果您希望条形图总是比其默认高度大20px,则代码应该向条形图的高度添加20px,而不是将其设置为64px(44px 20px) .
Swift 3 + 4:
例:
通常,程序员需要将其约束到顶部或底部,因此这些方法可以提供帮助
对于iPhone X之前,这些方法返回:0
对于iPhone X:44和34相应
然后只需将这些额外内容添加到顶部或底部约束
对于那些获得2001px而不是2436px的本地边界高度(像我一样),这是因为你在iOS 11(Xcode 8而不是Xcode 9)之前使用较旧的SDK构建了你的应用程序 . 使用较旧的SDK,iOS将在iPhone X上显示“黑盒子”应用,而不是将屏幕边缘到边缘延伸,超出顶部“传感器缺口” . 这会减小屏幕尺寸,这就是该属性返回2001而不是2436的原因 .
最简单的解决方案是,如果您只对设备检测感兴趣,只需检查两种尺寸 . 我使用这种方法检测FaceID,同时使用较旧的Xcode SDK构建,该SDK没有指定生物识别类型的ENUM值 . 在这种情况下,使用屏幕高度的设备检测似乎是了解设备是否具有FaceID与TouchID而不必更新Xcode的最佳方式 .
一世详细阐述了你对其他人的回答,并在UIDevice上迅速扩展 . 我喜欢快速的枚举和“一切有序”和雾化 . 我已经创建了适用于设备和模拟器的解决方案 .
优点: - 简单的界面,用途,例如
UIDevice.current.isIPhoneX
-UIDeviceModelType
枚举使您能够轻松扩展要在应用中使用的模型特定功能和常量,例如: cornerRadius缺点: - 它是特定于模型的解决方案,而不是特定于分辨率的解决方案 - 例如如果Apple将 生产环境 具有相同规格的另一个型号,这将无法正常工作,您需要添加另一个型号才能使这项工作=>您需要更新您的应用程序 .
我依靠状态栏框架高度来检测它是否是iPhone X:
这是申请人像 . 您还可以根据设备方向检查尺寸 . 此外,在其他iPhone上,状态栏可能是隐藏的,因此帧高度为
0
. 在iPhone X上,状态栏永远不会隐藏 .我正在使用Peter Kreinz's code(因为它很干净并且做了我需要的东西)但后来我意识到它适用于设备是在肖像上(因为顶部填充将在顶部,显然)所以我创建了一个扩展来处理所有的方向与各自的填充,无需中继屏幕尺寸:
在您的通话网站上,您只需:
不要像其他解决方案所建议的那样使用屏幕像素大小,这很糟糕,因为它可能导致未来设备出现误报;如果UIWindow尚未呈现(AppDelegate),则无法在横向应用程序中运行,并且如果设置了比例,则可能在模拟器上失败 .
相反,我为此目的制作了一个宏,它非常易于使用并依赖于硬件标志来防止上述问题 .
编辑:更新以支持iPhoneX,iPhone XS,iPhoneXR,iPhoneXS Max
使用:
是的,真的 .
宏:
只需复制粘贴到任何地方,我更喜欢我的.h文件的底部
@end
我最近不得不解决同样的问题 . 虽然这个问题得到了明确的回答(“否”),但这可能有助于其他需要iPhone X特定布局行为的人 .
我对该设备是否是iPhone X并不感兴趣 . 我对该设备是否有缺口显示感兴趣 .
你也可以在同一行写一个
hasOnScreenHomeIndicator
变量(虽然可以查看底部的安全区域?) .以上使用
UIView
上的扩展名,方便访问iOS 10及更早版本的安全区域insets .或者,您可以查看'DeviceKit'pod . 安装完成后,您需要做的就是检查设备:
有几个原因想知道设备是什么 .
您可以检查设备高度(和宽度) . 这对布局很有用,但如果您想知道确切的设备,通常不希望这样做 .
出于布局目的,您还可以使用
UIView.safeAreaInsets
.如果要显示设备名称(例如,要包含在电子邮件中以进行诊断),在使用
sysctl ()
检索设备模型后,可以使用等效的名称来表示名称:为了快速解决问题,我喜欢这个:
检测设备是否为iPhone X的最佳和最简单的方法是,
https://github.com/stephanheilner/UIDevice-DisplayName
对于iPhone X,标识符为 "iPhone10,3" or "iPhone10,6" .