Detecta si el dispositivo es iPhone X

Mi aplicación para iOS usa una altura personalizada para UINavigationBar que genera algunos problemas en el nuevo iPhone X.

¿Alguien ya sabe cómo detectar confiablemente programáticamente (en Objective-C) si una aplicación se está ejecutando en el iPhone X?

EDITAR:

Por supuesto, es posible verificar el tamaño de la pantalla. Sin embargo, me pregunto si existe algún método de “comstackción” como TARGET_OS_IPHONE para detectar iOS …

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

EDICION 2:

No creo que mi pregunta sea un duplicado de la pregunta vinculada. Por supuesto, hay métodos para “medir” diferentes propiedades del dispositivo actual y para usar los resultados para decidir qué dispositivo se usa. Sin embargo, este no era el verdadero punto de mi pregunta, como traté de enfatizar en mi primera edición.

La pregunta real es: “¿Es posible detectar directamente si el dispositivo actual es un iPhone X (por ejemplo, mediante alguna función SDK) o tengo que usar mediciones indirectas” ?

Con las respuestas dadas hasta ahora, asumo que la respuesta es “No, no hay métodos directos. Las mediciones son el camino a seguir”.

Según su pregunta, la respuesta es No, no hay métodos directos, para obtener más información, puede obtener la información de aquí1 y aquí2

si quieres detectar la altura del iphone X usa 2436px

Tamaños y orientaciones de la pantalla del dispositivo

enter image description here

veloz 3 y más

 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") default: print("unknown") } } 

C objective

  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: printf("iPhone X"); break; default: printf("unknown"); } } 

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"); } //etc... } 

basado en tu pregunta como sigue

o use screenSize.height como float 812.0f no int 812

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

para más información puede obtener aquí

ACTUALIZAR

NO use la propiedad userInterfaceIdiom para identificar el tipo de dispositivo, como lo explica la documentación de Apple,

Para aplicaciones universales, puede usar esta propiedad para adaptar el comportamiento de su aplicación a un tipo específico de dispositivo. Por ejemplo, los dispositivos iPhone y iPad tienen diferentes tamaños de pantalla, por lo que es posible que desee crear diferentes vistas y controles según el tipo de dispositivo actual.

Es decir, esta propiedad solo se usa para identificar el estilo de vista de la aplicación en ejecución. Sin embargo, la aplicación de iPhone (no la universal) podría instalarse en un dispositivo iPad a través de App Store, en ese caso, userInterfaceIdiom también devolverá UIUserInterfaceIdiomPhone.

La forma correcta es obtener el nombre de la máquina vía uname , consulte este hilo para obtener más información.

Otra posibilidad, que funciona en iOS 11 porque el iPhone X es el único con una muesca en la parte superior. Eso es lo que realmente estoy detectando aquí:

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

Y, por supuesto, es posible que deba verificar las áreas de las áreas seguras izquierda y derecha si se encuentra en orientación horizontal.

Editar: _window es la ventana UI de AppDelegate, donde esta comprobación se realiza en la aplicación didFinishLaunchingWithOptions.

Puede hacer esto para detectar el dispositivo iPhone X según la dimensión.

Rápido

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

C objective

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

enter image description here

Pero ,

Esto no es suficiente. ¿Qué pasa si Apple anuncia el próximo iPhone con la misma dimensión de iPhone X. por lo que la mejor manera es utilizar la cadena de Hardware para detectar el dispositivo.

Para un dispositivo más nuevo, la cadena de hardware es la siguiente.

iPhone 8 – iPhone10,1 o iPhone 10,4

iPhone 8 Plus – iPhone10,2 o iPhone 10,5

iPhone X – iPhone10,3 o iPhone10,6

Verifique el nombre del modelo / máquina del dispositivo , NO use el conteo de puntos / píxeles en su código directamente, ¡es un código difícil !

 #import  NSString* deviceName() { struct utsname systemInfo; uname(&systemInfo); return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; } 

Resultado:

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

Consulte esta respuesta .

Implementación completa del código:

 #import  BOOL IsiPhoneX(void) { static BOOL isiPhoneX = NO; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ #if TARGET_IPHONE_SIMULATOR NSString *model = NSProcessInfo.processInfo.environment[@"SIMULATOR_MODEL_IDENTIFIER"]; #else struct utsname systemInfo; uname(&systemInfo); NSString *model = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; #endif isiPhoneX = [model isEqualToString:@"iPhone10,3"] || [model isEqualToString:@"iPhone10,6"]; }); return isiPhoneX; } 

Deberás realizar diferentes detecciones de iPhone X según la necesidad real.

para tratar con la barra superior (barra de estado, barra de navegación) o el indicador de inicio inferior (barra de tabs), etc.

 class var hasSafeAreaInsets: Bool { if #available(iOS 11.0, tvOS 11.0, *) { return UIApplication.shared.delegate?.window??.safeAreaInsets != .zero } return false } 

para el tamaño del fondo, las funciones de pantalla completa, etc.

 class var isIphoneXOrBigger: Bool { return UIScreen.main.bounds.height >= 812 } 

Nota: eventualmente mezcle con UIDevice.current.userInterfaceIdiom == .phone
Nota: este método requiere tener un storyboard LaunchScreen o LaunchImages adecuado

para proporción de fondos, funciones de desplazamiento, etc.

 class var isIphoneXOrLonger: Bool { return UIScreen.main.bounds.height / UIScreen.main.bounds.width >= 812.0 / 375.0 } 

Nota: este método requiere tener un storyboard LaunchScreen o LaunchImages adecuado

para análisis, estadísticas, seguimiento, etc.

Obtenga el identificador de la máquina y compárelo con los valores documentados:

 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" } 

Para incluir el simulador como un iPhone X válido en su análisis:

 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" } 

para el soporte 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 } 

Después de mirar todas las respuestas, esto es lo que terminé haciendo:

Solución (compatible con 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 } } 

Utilizar

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

Nota

Pre Swift 4.1 puede verificar si la aplicación se ejecuta en un simulador de la siguiente manera:

 TARGET_OS_SIMULATOR != 0 

Desde Swift 4.1 en adelante, puede verificar si la aplicación se está ejecutando en un simulador utilizando la condición de plataforma de entorno de destino :

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

(el método anterior seguirá funcionando, pero este nuevo método es más a prueba de futuro)

 #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) #define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0) #define IS_IPAD_DEVICE [(NSString*)[UIDevice currentDevice].model hasPrefix:@"iPad"] 

Nota: – Tenga cuidado, funciona bien solo para orientación vertical

Todas estas respuestas basadas en dimensiones son susceptibles de un comportamiento incorrecto en futuros dispositivos. Trabajarán hoy, pero ¿qué pasa si hay un iPhone el próximo año que sea del mismo tamaño pero que tenga la cámara, etc. debajo del cristal para que no haya “muescas”? Si la única opción es actualizar la aplicación, entonces es una solución deficiente para usted y sus clientes.

También puede verificar la cadena del modelo de hardware como “iPhone10,1”, pero eso es problemático porque a veces Apple publica diferentes números de modelo para diferentes operadores alrededor del mundo.

El enfoque correcto es rediseñar el diseño superior o resolver los problemas que tiene con la altura de la barra de navegación personalizada (en eso me concentraré). Pero, si decides no hacer ninguna de esas cosas, date cuenta de que lo que sea que estés haciendo es un truco para que esto funcione hoy , y tendrás que corregirlo en algún momento, tal vez varias veces, para mantener los ataques. trabajando.

Sí, es posible. Descargue la extensión UIDevice-Hardware (o instálela a través de CocoaPod ‘UIDevice-Hardware’) y luego use:

 NSString* modelID = [[[UIDevice currentDevice] modelIdentifier]; BOOL isIphoneX = [modelID isEqualToString:@"iPhone10,3"] || [modelID isEqualToString:@"iPhone10,6"]; 

Tenga en cuenta que esto no funcionará en el simulador, solo en el dispositivo real.

SWIFT 4 respuesta

Mehod 1:

Al usar window?.safeAreaInsets.top

  var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { window = UIWindow(frame: UIScreen.main.bounds) if #available(iOS 11.0, *) { if (window?.safeAreaInsets.top)! > CGFloat(0.0) || window?.safeAreaInsets != .zero { print("iPhone X") } else { print("Not iPhone X") } } return true } 

Método 2: Nota: necesita un dispositivo real para la prueba

Referencia

  let deviceType = UIDevice.current.modelName if deviceType.range(of:"iPhone10,3") != nil || deviceType.range(of:"iPhone10,6") != nil { print("iPhone X") } else { print("Not iPhone X") } 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 } } 

Según la respuesta de @ saswanb, esta es una versión de Swift 4:

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

Sé que es solo una solución Swift , pero podría ayudar a alguien.

Tengo globals.swift en cada proyecto y una de las cosas que siempre agrego es DeviceType para detectar fácilmente el dispositivo del usuario:

 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 } 

Entonces para usarlo:

 if DeviceType.iPhoneX { print("This executes only on iPhoneX") } 

Swift 3 + 4:

sin necesidad de ningún tamaño de píxel de tamaño de dispositivo

 //UIApplication+SafeArea.swift extension UIApplication { static var isDeviceWithSafeArea:Bool { if #available(iOS 11.0, *) { if let topPadding = shared.keyWindow?.safeAreaInsets.top, topPadding > 0 { return true } } return false } } 

Ejemplo:

 if UIApplication.isDeviceWithSafeArea { //eg change the frame size height of your UITabBar } 

No debe suponer que el único dispositivo que Apple lanza con una altura UINavigationBar diferente será el iPhone X. Intente resolver este problema utilizando una solución más genérica. Si desea que la barra siempre sea 20px más grande que su altura predeterminada, su código debe agregar 20px a la altura de la barra, en lugar de establecerlo en 64px (44px + 20px).

Todas las respuestas que usan la height son solo la mitad de la historia por una razón. Si va a marcar de esa manera cuando la orientación del dispositivo es landscapeLeft o landscapeRight la comprobación fallará, porque la height se intercambia con el width .

Es por eso que mi solución se ve así en 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 } } 
 struct ScreenSize { static let width = UIScreen.main.bounds.size.width static let height = UIScreen.main.bounds.size.height static let maxLength = max(ScreenSize.width, ScreenSize.height) static let minLength = min(ScreenSize.width, ScreenSize.height) static let frame = CGRect(x: 0, y: 0, width: ScreenSize.width, height: ScreenSize.height) } struct DeviceType { static let iPhone4orLess = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength < 568.0 static let iPhone5orSE = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 568.0 static let iPhone678 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 667.0 static let iPhone678p = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 736.0 static let iPhoneX = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 812.0 static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.maxLength == 1024.0 static let IS_IPAD_PRO = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.maxLength == 1366.0 } 
 #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) #define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0f) 
 - (BOOL)isIphoneX { if (@available(iOS 11.0, *)) { UIWindow *window = UIApplication.sharedApplication.keyWindow; CGFloat topPadding = window.safeAreaInsets.top; if(topPadding>0) { return YES; } else { return NO; } } else { return NO; } } 

Por lo general, el Progtwigdor lo necesita para restringir a la parte superior o inferior, por lo que estos métodos pueden ayudar

 static func extraTop() -> CGFloat { var top: CGFloat = 0 if #available(iOS 11.0, *) { if let t = UIApplication.shared.keyWindow?.safeAreaInsets.top { top = t } } return top } static func extraBottom() -> CGFloat { var bottom: CGFloat = 0 if #available(iOS 11.0, *) { if let b = UIApplication.shared.keyWindow?.safeAreaInsets.bottom { bottom = b } } return bottom } 

Para antes del iPhone X estos métodos regresan: 0

Para iPhone X: 44 y 34 en consecuencia

Luego solo agrega estos extras a las restricciones superiores o inferiores

Para aquellos que obtienen 2001px en vez de 2436px para la altura de los límites nativos (como yo), es porque usted construyó su aplicación con un SDK anterior, antes de iOS 11 (Xcode 8 en lugar de Xcode 9). Con un SDK anterior, iOS mostrará las aplicaciones en “caja negra” en el iPhone X en lugar de extender la pantalla de borde a borde, más allá de la “muesca del sensor” superior. Esto reduce el tamaño de la pantalla por lo que esa propiedad devuelve 2001 en lugar de 2436.

La solución más simple es simplemente verificar ambos tamaños si solo está interesado en la detección de dispositivos. Utilicé este método para detectar FaceID mientras construía con un Xcode SDK anterior que no tiene el valor ENUM que especifica el tipo biométrico. En esta situación, la detección del dispositivo usando la altura de la pantalla parecía ser la mejor manera de saber si el dispositivo tenía FaceID versus TouchID sin tener que actualizar Xcode.

Exploré en las respuestas de otras personas e hice una rápida extensión en UIDevice. Me gustan los enums rápidos y “todo en orden” y atomizado. Creé una solución que funciona tanto en dispositivos como en simuladores.

Ventajas: – interfaz simple, uso, por ejemplo UIDevice.current.isIPhoneXUIDeviceModelType enum le brinda la capacidad de extender fácilmente las características y las constantes específicas del modelo que desea usar en su aplicación, por ejemplo, cornerRadius

Desventaja: – es una solución específica para el modelo, no específica para la resolución – por ejemplo, si Apple producirá otro modelo con las mismas especificaciones, esto no funcionará correctamente y deberá agregar otro modelo para que esto funcione => usted necesita actualizar su aplicación

 extension UIDevice { enum UIDeviceModelType : Equatable { ///iPhoneX case iPhoneX ///Other models case other(model: String) static func type(from model: String) -> UIDeviceModelType { switch model { case "iPhone10,3", "iPhone10,6": return .iPhoneX default: return .other(model: model) } } static func ==(lhs: UIDeviceModelType, rhs: UIDeviceModelType) -> Bool { switch (lhs, rhs) { case (.iPhoneX, .iPhoneX): return true case (.other(let modelOne), .other(let modelTwo)): return modelOne == modelTwo default: return false } } } var simulatorModel: String? { guard TARGET_OS_SIMULATOR != 0 else { return nil } return ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] } var hardwareModel: String { var systemInfo = utsname() uname(&systemInfo) let machineMirror = Mirror(reflecting: systemInfo.machine) let model = 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 model } var modelType: UIDeviceModelType { let model = self.simulatorModel ?? self.hardwareModel return UIDeviceModelType.type(from: model) } var isIPhoneX: Bool { return modelType == .iPhoneX } } 

Confío en la altura del Marco de la barra de estado para detectar si se trata de un iPhone X:

 if UIApplication.shared.statusBarFrame.height >= CGFloat(44) { // It is an iPhone X } 

Esto es para la aplicación un retrato. También puede verificar el tamaño de acuerdo con la orientación del dispositivo. Además, en otros iPhones, la barra de estado puede estar oculta, por lo que la altura del cuadro es 0 . En el iPhone X, la barra de estado nunca se oculta.

Estaba usando el código de Peter Kreinz (porque estaba limpio e hice lo que necesitaba) pero luego me di cuenta de que funciona justo cuando el dispositivo está en retrato (ya que el relleno superior estará en la parte superior, obviamente). Así que creé una extensión para manejar todo orientaciones con sus respectivos rellenos, sin retransmitir en el tamaño de la pantalla:

 extension UIDevice { var isIphoneX: Bool { if #available(iOS 11.0, *), isIphone { if isLandscape { if let leftPadding = UIApplication.shared.keyWindow?.safeAreaInsets.left, leftPadding > 0 { return true } if let rightPadding = UIApplication.shared.keyWindow?.safeAreaInsets.right, rightPadding > 0 { return true } } else { if let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top, topPadding > 0 { return true } if let bottomPadding = UIApplication.shared.keyWindow?.safeAreaInsets.bottom, bottomPadding > 0 { return true } } } return false } var isLandscape: Bool { return UIDeviceOrientationIsLandscape(orientation) || UIInterfaceOrientationIsLandscape(UIApplication.shared.statusBarOrientation) } var isPortrait: Bool { return UIDeviceOrientationIsPortrait(orientation) || UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation) } var isIphone: Bool { return self.userInterfaceIdiom == .phone } var isIpad: Bool { return self.userInterfaceIdiom == .pad } } 

Y en su sitio de llamadas usted simplemente:

 let res = UIDevice.current.isIphoneX 

Tuve que resolver el mismo problema recientemente. Y si bien esta pregunta se responde definitivamente (“No”), esto puede ayudar a otros que necesitan un comportamiento de diseño específico de iPhone X.

No estaba realmente interesado en si el dispositivo era iPhone X. Me interesaba saber si el dispositivo tenía una pantalla con muescas.

 private static var hasNotchedDisplay: Bool { if let window = UIApplication.shared.keyWindow { return (window.compatibleSafeAreaInsets.top > 20.0 || window.compatibleSafeAreaInsets.left > 0.0 || window.compatibleSafeAreaInsets.right > 0.0) } return false } 

También podría escribir una variable hasOnScreenHomeIndicator en la misma línea (aunque ¿podría ver el área segura inferior?).

Lo anterior usa mi extensión en UIView para acceder cómodamente a las inserciones de área segura en iOS 10 y anteriores.

 @objc public extension UIView { @objc public var compatibleSafeAreaInsets: UIEdgeInsets { if #available(iOS 11.0, *) { return safeAreaInsets } else { return .zero } } @objc public var compatibleSafeAreaLayoutGuide: UILayoutGuide { if #available(iOS 11.0, *) { return safeAreaLayoutGuide } else { return layoutMarginsGuide } } } 

Hay varias razones para querer saber qué es el dispositivo.

  1. Puede verificar la altura (y el ancho) del dispositivo. Esto es útil para el diseño, pero generalmente no quiere hacer eso si quiere saber el dispositivo exacto.

  2. Para propósitos de diseño, también puede usar UIView.safeAreaInsets .

  3. Si desea mostrar el nombre del dispositivo, por ejemplo, para ser incluido en un correo electrónico con fines de diagnóstico, después de recuperar el modelo del dispositivo usando sysctl () , puede usar el equivalente de esto para calcular el nombre:

     $ curl http://appledevicenames.com/devices/iPhone10,6 iPhone X 

Para una solución rápida, me gusta esto:

 let var:CGFloat = (UIDevice.current.userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436) ?  :  

La mejor y más fácil forma de detectar si el dispositivo es el iPhone X es

https://github.com/stephanheilner/UIDevice-DisplayName

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

Y el identificador es “iPhone10,3” o “iPhone10,6” para iPhone X.

NO use el tamaño de píxel de la pantalla como lo sugirieron otras soluciones, esto es malo, ya que puede dar lugar a falsos positivos para futuros dispositivos; no funcionará si UIWindow aún no se ha procesado (AppDelegate), no funcionará en las aplicaciones de paisaje y puede fallar en el simulador si se establece la escala.

En cambio, he creado una macro para este propósito, es muy fácil de usar y depende de indicadores de hardware para evitar los problemas antes mencionados.


Usar:

 if (IS_DEVICE_IPHONEX) { //do stuff } 

Sí, realmente.


Macro:

Solo copie y pegue esto en cualquier lugar, prefiero la parte inferior de mi archivo .h después de @end

 #import  #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";\ return ([__modelIdentifier isEqualToString:__iPhoneX_GSM_Identifier] || [__modelIdentifier isEqualToString:__iPhoneX_CDMA_Identifier]);\ })()\ ) 

Alternatively, you can check out ‘ DeviceKit ‘ pod. Once installed, all you need to do to check the device is:

 import DeviceKit let device = Device() if device == .iPhoneX { // place your code here }