Détecter si l'appareil est iPhone X

mon application iOS utilise une hauteur personnalisée pour le UINavigationBar ce qui entraîne des problèmes sur le nouvel iPhone X.

est-ce que quelqu'un sait déjà fiable détecter programmatiquement (en Objectif-C) si une application est en cours d'exécution sur iPhone X?

EDIT:

bien sûr, vérifier la taille de l'écran est possible, cependant, je me demande s'il y a une certaine méthode "build in" comme TARGET_OS_IPHONE pour détecter iOS...

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

EDIT 2:

je ne pense pas que ma question est un doublon de la question. Bien sûr, il existe des méthodes de "mesurer" des propriétés différentes de l'appareil et utiliser les résultats pour décider quel appareil est utilisé. Cependant, ce n'était pas le point réel de ma question comme j'ai essayé de souligner dans ma première édition.

la vraie question Est: "Est-il possible de détecter directement si l'appareil est un iPhone X (par exemple, par certains SDK) ou dois-je utiliser des mesures indirectes" ?

Par les réponses apportées jusqu'à présent, je suppose que la réponse est "Non, il n'y a pas de méthodes directes. Les mesures sont la voie à suivre".

180
demandé sur Kiran Sarvaiya 2017-09-13 11:12:05

30 réponses

basé sur votre question, la réponse est non, il n'y a pas de méthodes directes, pour plus d'informations vous pouvez obtenir les informations de here1 et here2 1519150920"

si vous voulez détecter l'iphone X Hauteur utiliser 2436px

tailles D'écran et résolutions de L'appareil

enter image description here

tailles et Orientations de L'écran du dispositif

enter image description here

Swift 3 et plus

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")
        case 2688:
            print("iPhone Xs Max")
        case 1792:
            print("iPhone Xr")
        default:
            print("unknown")
        }
    }

Objectif 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:
                printf("iPhone X, Xs");
                break;
               case 2688:
            print("iPhone Xs Max")
           case 1792:
            print("iPhone Xr")
            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...
}

basé sur votre question comme suit

ou utilisez screenSize.hauteur en tant que flotteur 812.0f not 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");
}

pour plus d'informations vous pouvez obtenir ici

Swift

ou de détecter avec topNotch

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

Objectif C

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

mise à JOUR

N'utilisez pas la propriété userInterfaceIdiom pour identifier le type d'appareil, comme l'explique la documentation Apple,

Pour des applications universelles, vous pouvez utiliser cette propriété pour adapter le comportement de votre application pour un type d'appareil. Par exemple, les appareils iPhone et iPad ont différentes tailles d'écran, donc vous pourriez vouloir créer différentes vues et contrôles selon le type de l'appareil actuel.

C'est-à-dire que cette propriété est juste utilisée pour identifier le style de vue de l'application en cours d'exécution. Cependant, l'application iPhone (pas l'universelle) pourrait être installé dans l'appareil iPad via App store, dans ce cas, l'utilisateur interfaceidiom retournera L'Uiuser Interfaceidiomphone, aussi.

la bonne façon est d'obtenir le nom de la machine via uname , cochez ce thread pour plus de détails.

225
répondu Anbu.karthik 2018-10-05 09:55:31

une autre possibilité, qui fonctionne sur iOS 11 et iOS 12 parce que l'iPhone X est le seul avec un cran au sommet et un médaillon de 44. C'est ce que je détecte vraiment ici:

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

et bien sûr, vous pourriez avoir besoin de vérifier les inserts de gauche et de droite de la zone de sécurité si vous êtes dans l'orientation du paysage.

Edit: _window est le UIWindow de l'AppDelegate, où cette vérification est effectuée en application didFinishLaunchingWithOptions.

réponse mise à jour pour iOS 12 pour vérifier si top > 20 au lieu de top > 0.

77
répondu saswanb 2018-10-04 16:19:53

vous pouvez faire comme ceci pour détecter iPhone x appareil selon la dimension.

Swift

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

Objectif-C

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

enter image description here

mais ,

Ce n'est pas suffisant. Que faire si Apple a annoncé la prochaine iPhone avec la même dimension de iPhone X. Donc la meilleure façon est d'utiliser la chaîne de matériel pour détecter l'appareil.

pour la chaîne de caractères de l'appareil le plus récent est comme ci-dessous.

iPhone 8 - iPhone10,1 ou iPhone 10,4 151950920"

iPhone 8 Plus - iPhone10,2 ou iPhone 10,5 151950920"

iPhone x - iPhone10,3 or iPhone10,6

41
répondu Jaydeep 2018-02-22 06:44:36

vous devez effectuer différentes détections de l'iPhone X en fonction du besoin réel.

pour traiter avec l'échelon supérieur (statusbar, navbar), etc.

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: 20.0 on iPhone 8 on iOS 12+.
        return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
    }
    return false
}

pour le traitement de l'indicateur de maison inférieur (tabbar), etc.

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

pour la taille des fonds, les caractéristiques plein écran, etc.

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

Note: éventuellement le mélanger avec UIDevice.current.userInterfaceIdiom == .phone

Note: cette méthode nécessite d'avoir un panneau de rangement de LaunchScreen ou des limages de launch

pour les arrière-plans ratio, défilement, etc.

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
}

Note: cette méthode nécessite d'avoir un panneau de rangement de L'écran de launch ou des limages de launch

à des fins d'analyse, les statistiques, le suivi, etc.

récupérez l'Identificateur de la machine et comparez-le à des valeurs documentées:

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

comprend la simulateur de validité de l'iPhone X dans votre analyse:

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

pour inclure iPhone XS, XS Max et XR, il suffit de rechercher des modèles commençant par " iPhone11,":

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

for faceID support

import LocalAuthentication
/// will fail if user denies canEvaluatePolicy(_:error:)
class var canUseFaceID: Bool {
    if #available(iOS 11.0, *) {
        return LAContext().biometryType == .typeFaceID
    }
    return false
}
39
répondu Cœur 2018-09-13 03:29:37

Vérifiez le nom du modèle de périphérique / machine , N'utilisez pas le nombre de points/pixels dans votre code directement, c'est code dur !

#import <sys/utsname.h>

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

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

résultat:

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

Consultez cette réponse .

la Pleine mise en œuvre du code:

#import <sys/utsname.h>

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;
}
37
répondu Itachi 2017-11-10 02:04:15
#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_IPHONE_X (IS_IPHONE & & & [[UIScreen mainScreen] bounds].taille.hauteur == 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"]

Note: - attention, il ne fonctionne bien que pour l'orientation portrait

23
répondu Jagveer Singh 2018-09-20 14:27:03

Après avoir examiné toutes les réponses c'est ce que j'ai fait:

Solution (compatible 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
    }
}

Utiliser

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

Note

Pre Swift 4.1 vous pouvez vérifier si l'application fonctionne sur un simulateur comme ceci:

TARGET_OS_SIMULATOR != 0

à partir de Swift 4.1 vous pouvez vérifier si l'application fonctionne sur un simulateur en utilisant le environnement Cible de la plateforme de la condition :

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

(l'ancienne méthode fonctionnera toujours, mais cette nouvelle méthode est plus dans l'avenir)

22
répondu Cloud9999Strife 2018-08-07 06:54:52

toutes ces réponses basées sur les dimensions sont susceptibles d'un comportement incorrect sur les dispositifs futurs. Ils fonctionneront aujourd'hui, mais s'il y a un iPhone l'année prochaine qui est de la même taille mais qui a la caméra, etc. sous la vitre pour qu'il n'y ait pas de "pas"?"Si la seule option est de mettre à jour l'application, alors c'est une mauvaise solution pour vous et vos clients.

vous pouvez aussi vérifier la chaîne de caractères du modèle matériel comme "iPhone10, 1", mais c'est problématique parce que parfois Apple publie différents numéros de modèles pour différents transporteurs dans le monde.

l'approche correcte est de redessiner la disposition du haut, ou de résoudre les problèmes que vous avez avec la hauteur de la barre de navigation personnalisée (c'est ce que je me concentrerais sur). Mais, si vous décidez de ne pas faire l'une ou l'autre de ces choses , réalisez que quoi que vous fassiez est un piratage pour faire en sorte que cela fonctionne aujourd'hui , et vous aurez besoin de le corriger à un moment donné, peut-être à plusieurs reprises, pour garder les hacks de travail.

17
répondu clarus 2017-09-19 02:29:57

Oui, c'est possible. Télécharger le UIDevice-extension matérielle (ou installer via CocoaPod 'UIDevice-Hardware') et ensuite utiliser:

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

noter que cela ne fonctionnera pas dans le simulateur, seulement sur le dispositif réel.

10
répondu Hendrik 2017-11-01 20:32:05

SWIFT 4+ Answer

iPhone X, XR, XS, XSMAX:

Note: Il faut un dispositif réel pour l'essai

référence

 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
    }
}
8
répondu Jack 2018-10-04 10:15:50

selon la réponse de @saswanb, c'est une version Swift 4:

var iphoneX = false
if #available(iOS 11.0, *) {
    if ((UIApplication.shared.keyWindow?.safeAreaInsets.top)! > CGFloat(0.0)) {
        iphoneX = true
    }
}
6
répondu MattOZ 2017-09-19 14:44:09

je sais que ce n'est qu'une solution Swift , mais cela pourrait aider quelqu'un.

j'ai globals.swift dans chaque projet et l'une des choses que j'ai toujours ajouter, c'est DeviceType de détecter facilement l'appareil de l'utilisateur:

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
}

puis l'utiliser:

if DeviceType.iPhoneX {
  print("This executes only on iPhoneX")
}
6
répondu budidino 2018-04-09 09:33:22

vous ne devez pas supposer que le seul appareil que Apple libère avec une hauteur UINavigationBar différente sera l'iPhone X. essayer de résoudre ce problème en utilisant une solution plus générique. Si vous voulez que la barre soit toujours plus grande de 20px que sa hauteur par défaut, votre code devrait ajouter 20px à la hauteur de la barre, au lieu de la mettre à 64px (44px + 20px).

4
répondu IMcD23 2017-09-18 23:57:45

toutes les réponses qui utilisent le height ne sont que la moitié de l'histoire pour une raison. Si vous allez vérifier comme cela lorsque l'orientation de l'appareil est landscapeLeft ou landscapeRight le contrôle échouera, parce que le height est remplacé par le width .

C'est pourquoi ma solution ressemble à ceci dans 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
    }
}
4
répondu DevAndArtist 2017-10-27 21:21:28
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
}
4
répondu Kiran Sarvaiya 2017-11-10 06:04:33

Swift 3 + 4:

sans besoin de la valeur de pixel de taille de périphérique

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

exemple:

if UIApplication.isDeviceWithSafeArea {
     //e.g. change the frame size height of your UITabBar
}
4
répondu Peter Kreinz 2018-01-30 15:36:50
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0f)
3
répondu alexander.pan 2017-09-13 08:39:34
- (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;
    }
}
3
répondu user6788419 2017-10-19 11:52:39

habituellement, le programmeur en a besoin pour forcer vers le haut ou vers le bas, de sorte que ces méthodes peuvent aider

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
}

pour avant iPhone x ces méthodes retourner: 0

pour iPhone X: 44 et 34 en conséquence

alors il suffit d'ajouter ces extras aux contraintes du haut ou du bas

3
répondu Andrey 2017-11-17 12:00:31

pour ceux qui obtiennent 2001px au lieu de 2436px pour la hauteur native bounds (comme moi), c'est parce que vous avez construit votre application avec un SDK plus ancien, avant iOS 11 (Xcode 8 au lieu de Xcode 9). Avec un SDK plus ancien, iOS affichera les applications " black boxed "sur l'iPhone X au lieu d'étendre l'écran bord à bord, au-delà du haut"sensor notch". Cela réduit la taille de l'écran qui est pourquoi cette propriété retourne 2001 au lieu de 2436.

la solution la plus simple est de vérifier pour les deux tailles si vous êtes seulement intéressé par la détection de périphérique. J'ai utilisé cette méthode pour détecter FaceID tout en construisant avec un vieux SDK Xcode qui n'a pas la valeur ENUM spécifiant le type biométrique. Dans cette situation, la détection de l'appareil à l'aide de la hauteur de l'écran semblait être la meilleure façon de savoir si L'appareil avait un FaceID vs TouchID sans avoir à mettre à jour Xcode.

3
répondu Jon Summers 2017-12-14 18:31:35

j'ai élaboré sur votre sur les réponses d'autre et fait l'extension rapide sur UIDevice. J'aime swift enums et "tout est en ordre" et atomisée. J'ai créé la solution qui fonctionne à la fois sur l'appareil et le simulateur.

avantages: - interface simple, utilisation par exemple UIDevice.current.isIPhoneX - UIDeviceModelType enum vous donne la possibilité d'étendre facilement les caractéristiques et les constantes spécifiques au modèle que vous voulez utiliser dans votre application, par exemple cornerRadius

désavantage: - c'est le modèle solution spécifique, pas de résolution spécifique-par exemple, si Apple produit un autre modèle avec les mêmes spécifications, cela ne fonctionnera pas correctement et vous devez ajouter un autre modèle pour que cela fonctionne => vous devez mettre à jour votre application.

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
    }
}
2
répondu deathhorse 2017-12-08 13:45:06

je me fie à la hauteur du cadre de la barre D'État pour détecter si c'est un iPhone X:

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

C'est pour l'application de l'onu portrait. Vous pouvez également vérifier la taille en fonction de l'orientation du périphérique. De plus, sur d'autres iPhones, la barre D'état peut être cachée, de sorte que la hauteur du cadre est 0 . Sur iPhone X, la barre D'État n'est jamais cachée.

2
répondu Tiois 2017-12-20 17:39:35

j'utilisais le code de Peter Kreinz (parce qu'il était propre et a fait ce dont j'avais besoin) mais ensuite j'ai réalisé qu'il fonctionne Juste quand l'appareil est sur le portrait (depuis rembourrage supérieur sera sur le dessus, évidemment) J'ai donc créé une extension pour gérer toutes les orientations avec ses rembourrages respectifs, sans relayer sur la taille de l'écran:

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

et sur votre site d'appel vous venez de:

let res = UIDevice.current.isIphoneX
2
répondu rgkobashi 2018-02-20 08:32:53

j'ai dû résoudre le même problème récemment. Et alors que cette question est définitivement répondue ("Non"), cela peut aider d'autres qui ont besoin iPhone X comportement de layout spécifique.

Je n'étais pas vraiment intéressé à savoir si l'appareil était iPhone X. j'étais intéressé à savoir si l'appareil avait un affichage entaillé.

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
}

vous pouvez aussi écrire une variable hasOnScreenHomeIndicator dans le même sens (bien que vérifier la zone de sécurité du bas, peut-être?).

ce qui précède utilise mon extension sur UIView pour un accès pratique à la zone de sécurité insets sur iOS 10 et plus tôt.

@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
        }
    }
}
1
répondu simeon 2018-06-01 03:32:11

alternativement, vous pouvez sortir" DeviceKit " pod. Une fois installé, tout ce que vous devez faire pour vérifier l'appareil est:

import DeviceKit
let device = Device()
if device == .iPhoneX {
  // place your code here
}
1
répondu Islombek Hasanov 2018-08-04 16:57:34

N'utilisez pas la taille de pixel d'écran comme d'autres solutions l'ont suggéré, c'est mauvais car il peut en résulter de faux positifs pour les dispositifs futurs; ne fonctionnera pas si UIWindow n'a pas encore rendu (AppDelegate), ne fonctionnera pas dans les applications de paysage, et peut échouer sur simulateur si l'échelle est définie.

j'ai, au lieu de cela, fait une macro à cet effet, il est très facile à utiliser et s'appuie sur des indicateurs matériels pour prévenir les problèmes mentionnés ci-dessus.

modifier: mis à jour pour soutenir iPhoneX, iPhone XS, iPhoneXR, iPhoneXS Max


À Utiliser:

if (IS_DEVICE_IPHONEX) {
    //do stuff
}

Oui, vraiment.


Macro:

il suffit de copier coller ceci n'importe où, je préfère le bas de mon .h du fichier après le @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]);\
})()\
)
1
répondu Albert Renshaw 2018-09-26 20:48:38

Il y a plusieurs raisons de vouloir savoir ce que l'appareil est.

  1. vous pouvez vérifier la hauteur (et la largeur) de l'appareil. Ceci est utile pour la mise en page, mais vous ne voulez pas le faire si vous voulez connaître l'exacte appareil.

  2. pour la mise en page, vous pouvez également utiliser UIView.safeAreaInsets .

  3. si vous voulez afficher le nom du périphérique, par exemple, pour être inclus dans un email à des fins de diagnostic, après avoir récupéré le modèle de l'appareil en utilisant sysctl () , vous pouvez utiliser l'équivalent de ceci pour représenter le nom:

    $ curl http://appledevicenames.com/devices/iPhone10,6
    
    iPhone X
    
0
répondu Hwee-Boon Yar 2017-10-14 15:48:31

pour une correction rapide, j'aime ça:

let var:CGFloat = (UIDevice.current.userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436) ? <iPhoneX> : <AllOthers>
0
répondu Andres Canella 2018-01-04 23:09:43

la meilleure et la plus facile façon de détecter si l'appareil est iPhone X est,

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

et l'identificateur est soit "iPhone10, 3" ou "iPhone10, 6" pour iPhone X.

0
répondu satheeshwaran 2018-06-29 09:22:46

Dans Portrait uniquement j'utilise le point de vue de l'image de la largeur et de la hauteur de vérifier:

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

}

les dimensions de l'écran de portrait sont indiquées ici

enter image description here

0
répondu Lance Samaria 2018-09-16 01:01:45