283 votes

Détecter si l'appareil est l'iPhone X

Mon application iOS utilise une hauteur personnalisée pour l' UINavigationBar ce qui conduit à des problèmes sur le nouvel iPhone X.

Quelqu'un sais déjà comment fiable de détecter par programme (en Objective-C) si une application est en cours d'exécution sur l'iPhone X?

EDIT:

Bien sûr, la vérification de la taille de l'écran est possible, cependant, je me demande si il y a des "construire en" méthode 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 moment de ma question que j'ai essayé de mettre l'accent 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 fonction) 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".

423voto

Anbu.Karthik Points 2805

Basé sur votre question, la réponse est non. Il n'existe pas de méthodes. Pour plus d'informations, vous pouvez obtenir les informations ici:

et

L'iPhone X hauteur est 2436 px

À partir de l'Appareil Tailles d'Écran et résolutions:

enter image description here

À partir de l'Écran du Périphérique de Tailles et d'Orientations:

enter image description here

Swift 3 et plus tard:

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

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:
            printf("iPhone X, XS");
            break;

        case 2688:
            printf("iPhone XS Max");
            break;

        case 1792:
            printf("iPhone XR");
            break;

        default:
            printf("Unknown");
            break;
    }
}

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");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 2688) {
        Console.WriteLine("iPhone XS Max");
    } else if ((UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale) == 1792) {
        Console.WriteLine("iPhone XR");
    } else {
        Console.WriteLine("Unknown");
    }
}

Basé sur votre question comme suit:

Ou utiliser screenSize.height comme le flotteur 812.0f non 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 vous référer à la page suivante dans iOS Human Interface Guidelines:

Swift:

Détecter avec topNotch:

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

    return false
}

Objective-C:

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

    return  NO;
}

Mise à JOUR:

Ne pas utiliser l' userInterfaceIdiom de la propriété d'identifier le type d'appareil, comme la documentation pour userInterfaceIdiom explique:

Pour des applications universelles, vous pouvez utiliser cette propriété pour adapter le comportement de votre application pour un type d'appareil. Par exemple, l'iPhone et l'iPad ont différentes tailles d'écran, de sorte que vous pouvez créer différents points de vue et des contrôles basés sur le type de l'appareil actuel.

C'est, cette propriété est utilisée pour identifier l'application en cours d'exécution du style d'affichage. Toutefois, l'application iPhone (pas l'universel) peut être installé dans le dispositif iPad via l'App store, dans ce cas, l' userInterfaceIdiom sera de retour l' UIUserInterfaceIdiomPhone, trop.

La bonne façon est d'obtenir le nom de la machine via uname. Vérifiez les éléments suivants pour plus de détails:

108voto

saswanb Points 1164

Une autre possibilité, qui fonctionne sur iOS 11 et iOS 12 parce que l'iPhone X est le seul avec une encoche en haut et un encart de 44. C'est ce que je suis vraiment détecter ici:

Objective-C:

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

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

Et bien sûr, vous pourriez avoir besoin de vérifier la gauche et la droite de la zone de sécurité encarts si vous êtes en orientation paysage.

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

Réponse de mise à jour pour iOS 12 pour vérifier si top > 24 plutôt que de haut > 0.

Edit: Dans le simulateur, vous pouvez aller à la Quincaillerie, de passer En appel la Barre de Statut. Faire qui me montre que la barre d'état hauteur ne change pas sur l'iPhone X sur iOS 11 ou iPhone XS iOS 12 lorsqu'il est engagé dans un appel. Tout ce qui change, c'est le temps de l'icône, qui obtient un fond vert, dans les deux cas. Voici un clin d'oeil:

enter image description here

80voto

Cœur Points 1538

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

pour traiter avec le haut de l'encoche (la barre d'état, barre de navigation), 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: 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
}

pour traiter le bas la maison d'un indicateur de la 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.
        // with home indicator: 20.0 on iPad Pro 12.9" 3rd generation.
        return UIApplication.shared.delegate?.window??.safeAreaInsets.bottom ?? 0 > 0
    }
    return false
}

pour les arrière-plans de la taille, 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
}

Remarque: finalement, le mélanger avec de l' UIDevice.current.userInterfaceIdiom == .phone
Remarque: cette méthode nécessite d'avoir un LaunchScreen storyboard ou la bonne LaunchImages

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
}

Remarque: cette méthode nécessite d'avoir un LaunchScreen storyboard ou la bonne LaunchImages

pour l'analyse, les statistiques, le suivi, etc.

Obtenez de l'identificateur de la machine et de la comparer aux 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"
}

Pour inclure le 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 l'iPhone XS, XS Max et XR, il suffit de regarder pour les modèles commençant par "iPhone11,":

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

pour faceID soutien

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

43voto

Jaydeep Points 3646

Vous pouvez le faire comme ceci pour détecter l'iPhone X appareil selon la dimension.

Swift

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

Objective - C

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

enter image description here

Mais,

Ce n'est pas assez. Si Apple a annoncé prochain iPhone avec la même dimension de l'iPhone X. donc, la meilleure façon est d'utiliser du Matériel de chaîne de détecter le périphérique.

Pour les nouveaux périphériques de la chaîne est comme ci-dessous.

iPhone 8 - iPhone10,1 ou iPhone 10,4

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

iPhone X - iPhone10,3 ou iPhone10,6

42voto

Itachi Points 401

Découvrez le modèle de l'appareil / le nom de la machine, NE PAS utiliser le point de/nombre de pixels dans votre code directement, c'est dur de code et de sens pour le périphérique matériel.

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

Reportez-vous à cette réponse.

La pleine mise en œuvre du code:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X