it-swarm.com.de

Stellen Sie fest, ob das Gerät iPhone X ist

Meine iOS-App verwendet eine benutzerdefinierte Höhe für die UINavigationBar, die auf dem neuen iPhone X zu Problemen führt. 

Weiß jemand bereits, wie er zuverlässig programmgesteuert (in Objective-C) _ erkennt, ob eine App auf dem iPhone X ausgeführt wird?

EDIT:

Natürlich ist es möglich, die Größe des Bildschirms zu überprüfen. Ich frage mich jedoch, ob es eine "eingebaute" Methode wie TARGET_OS_IPHONE gibt, um iOS zu erkennen ...

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

EDIT 2:

Ich denke nicht, dass meine Frage ein Duplikat der verknüpften Frage ist. Natürlich gibt es Methoden, um verschiedene Eigenschaften des aktuellen Geräts zu "messen" und anhand der Ergebnisse zu entscheiden, welches Gerät verwendet wird. Dies war jedoch nicht der eigentliche Punkt meiner Frage, wie ich in meinem ersten Schnitt betont habe. 

Die eigentliche Frage ist: "Ist es möglich, direkt festzustellen, ob das aktuelle Gerät ein iPhone X ist (z. B. durch eine SDK-Funktion) oder muss ich indirekte Messungen verwenden??

Bei den bisherigen Antworten gehe ich davon aus, dass die Antwort lautet: "Nein, es gibt keine direkten Methoden. Messungen sind der Weg". 

216
Andrei Herford

Basierend auf Ihrer Frage lautet die Antwort nein. Es gibt keine direkten Methoden. Weitere Informationen erhalten Sie hier:

und

Die Höhe des iPhone X beträgt 2436 px

Von Gerätegrößen und Auflösungen :

 enter image description here

Von Gerätegrößen und -ausrichtungen :

 enter image description here

Swift 3 und höher:

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

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

Basierend auf Ihrer Frage wie folgt:

Oder verwenden Sie screenSize.height als Float 812.0f nicht 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");
    }

Weitere Informationen finden Sie in den iOS-Richtlinien zur Benutzeroberfläche auf der folgenden Seite:

Swift:

Mit topNotch ermitteln:

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

    return false
}

Ziel c:

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

    return  NO;
}

UPDATE:

Verwenden Sie nicht die userInterfaceIdiom-Eigenschaft, um den Gerätetyp zu identifizieren, da die Dokumentation für userInterfaceIdiom Folgendes erklärt:

Für universelle Anwendungen können Sie diese Eigenschaft verwenden, um das Verhalten Ihrer Anwendung für einen bestimmten Gerätetyp anzupassen. Beispielsweise haben iPhone- und iPad-Geräte unterschiedliche Bildschirmgrößen. Daher möchten Sie möglicherweise unterschiedliche Ansichten und Steuerelemente basierend auf dem Typ des aktuellen Geräts erstellen.

Das heißt, diese Eigenschaft wird nur verwendet, um den Ansichtsstil der laufenden App zu identifizieren. Die iPhone-App (nicht die Universal-App) kann jedoch über den App Store auf dem iPad installiert werden. In diesem Fall gibt die userInterfaceIdiom auch die UIUserInterfaceIdiomPhone zurück.

Der richtige Weg ist, den Rechnernamen über uname zu erhalten. Überprüfen Sie Folgendes für Details:

306
Anbu.Karthik

Eine andere Möglichkeit, die auf iOS 11 und iOS 12 funktioniert, weil das iPhone X das einzige ist, das oben eine Kerbe hat und ein Inset von 44 aufweist.

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

Wenn Sie sich im Querformat befinden, müssen Sie möglicherweise den linken und den rechten Bereich des sicheren Bereichs überprüfen.

Edit: _window ist das UIWindow von AppDelegate, wo diese Überprüfung in der Anwendung didFinishLaunchingWithOptions durchgeführt wird.

Antwort für iOS 12 aktualisiert, um zu prüfen, ob top> 24 statt top> 0 ist.

Bearbeiten: Im Simulator können Sie zur Hardware-Statusleiste wechseln. Dadurch wird angezeigt, dass sich die Höhe der Statusleiste auf dem iPhone X unter iOS 11 oder iPhone XS iOS 12 nicht ändert, wenn ein Anruf eingeht. Alles, was sich ändert, ist das Zeitsymbol, das in beiden Fällen einen grünen Hintergrund hat. Hier ist ein Schnappschuss:

 enter image description here

92
saswanb

Sie müssen je nach Bedarf unterschiedliche Erkennungen des iPhone X durchführen.

für den Umgang mit der Oberklasse (Statusleiste, Navbar) usw.

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
}

für den Umgang mit der unteren Home-Anzeige (Tab-Leiste) usw.

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
}

für Hintergrundgröße, Vollbildfunktionen usw.

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

Hinweis: Mischen Sie es eventuell mit UIDevice.current.userInterfaceIdiom == .phone.
Hinweis: Diese Methode erfordert ein LaunchScreen-Storyboard oder entsprechende LaunchImages

für Hintergrundverhältnis, Scroll-Funktionen usw.

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
}

Hinweis: Diese Methode erfordert ein LaunchScreen-Storyboard oder entsprechende LaunchImages

für Analysen, Statistiken, Tracking usw.

Rufen Sie die Maschinen-ID ab und vergleichen Sie sie mit dokumentierten Werten:

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

So fügen Sie den Simulator als gültiges iPhone X in Ihre Analyse ein:

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

Um iPhone XS, XS Max und XR einzubeziehen, suchen Sie einfach nach Modellen, die mit "iPhone11" beginnen:

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

für die Unterstützung von 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
}
52
Cœur

Auf diese Weise können Sie das iPhone X -Gerät anhand der Abmessungen ermitteln.

Swift

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

Ziel c

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

 enter image description here

Aber,

Dies reicht nicht aus. Was ist, wenn Apple das nächste iPhone mit der gleichen Dimension von iPhone X ankündigt?.

Für neuere Geräte ist der Hardware-String wie folgt.

iPhone 8 - iPhone10,1 oder iPhone 10,4

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

iPhone X - iPhone10,3 oder iPhone10,6

41
Jaydeep

Check out das Gerätemodell/den Maschinennamen , NICHT die Punkt-/Pixelanzahl direkt in Ihrem Code verwenden, es ist hard code und für die Gerätehardware ohne Bedeutung.

#import <sys/utsname.h>

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

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

Ergebnis:

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

Siehe diese Antwort .

Vollständige Code-Implementierung:

#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
}
36
Itachi
#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)

definiere IS_IPHONE_X (IS_IPHONE && [[UIScreen-MainScreen] -Begrenzungen] .size.height == 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"]

Hinweis: - Seien Sie vorsichtig, es funktioniert nur für die Ausrichtung im Hochformat

25
Jagveer Singh

Nachdem ich mir alle Antworten angesehen hatte, tat ich es am Ende:

Lösung (Swift 4.1 kompatibel)

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

Benutzen

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

Hinweis

Pre Swift 4.1 können Sie überprüfen, ob die App auf einem Simulator ausgeführt wird:

TARGET_OS_SIMULATOR != 0

Ab Swift 4.1 können Sie mit der Bedingung Target-Umgebungsplattform prüfen, ob die App auf einem Simulator ausgeführt wird :

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

(Die ältere Methode wird immer noch funktionieren, aber diese neue Methode ist zukunftssicherer)

23
Cloud9999Strife

Alle diese auf Dimensionen basierenden Antworten sind anfällig für fehlerhaftes Verhalten auf zukünftigen Geräten. Sie funktionieren heute, aber was ist, wenn nächstes Jahr ein iPhone mit der gleichen Größe vorhanden ist, die Kamera usw. jedoch unter der Glasscheibe ist, so dass es keine "Kerbe" gibt? Wenn Sie nur die App aktualisieren möchten, ist dies eine schlechte Lösung für Sie und Ihre Kunden.

Sie können auch die Hardware-Modellzeichenfolge wie "iPhone10,1" überprüfen. Dies ist jedoch problematisch, da Apple manchmal unterschiedliche Modellnummern für verschiedene Netzbetreiber auf der ganzen Welt veröffentlicht.

Der richtige Ansatz besteht darin, das obere Layout neu zu gestalten oder die Probleme, die Sie mit der benutzerdefinierten Höhe der Navigationsleiste haben, zu lösen (darauf würde ich mich konzentrieren). Aber wenn Sie sich entscheiden, eines dieser Dinge nicht zu tun, müssen Sie erkennen, dass alles, was Sie tun, ein Hack ist, damit dies funktioniertheute, und Sie müssen es irgendwann korrigieren. Vielleicht mehrmals, um die Hacks am Laufen zu halten.

17
clarus

Swift 4+ Answer

iPhone X, XR, XS, XSMAX: ​​

Hinweis: Echtes Gerät zum Testen

Referenz

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

Ja, es ist möglich. Laden Sie die UIDevice-Hardware-Erweiterung herunter (oder installieren Sie sie über CocoaPod 'UIDevice-Hardware') und verwenden Sie

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

Beachten Sie, dass dies im Simulator nicht funktioniert, sondern nur auf dem tatsächlichen Gerät.

10
Hendrik

Ich weiß, dass es nur eine Swift-Lösung ist, aber es könnte jemandem helfen.

Ich habe globals.Swift in jedem Projekt und eines der Dinge, die ich immer hinzufüge, ist DeviceType, um das Gerät des Benutzers leicht zu erkennen:

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
  static let iPhoneXRMax   = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 896.0
  static var hasNotch: Bool {
    return iPhoneX || iPhoneXRMax
  }
}

Dann verwenden Sie es:

if DeviceType.hasNotch {
  print("This executes on all phones with a notch")
}

if DeviceType.iPhone678 {
  print("This executes on iPhones 6, 7 and 8")
}

Wenn Sie LaunchImage in Ihrem Projekt verwenden, stellen Sie sicher, dass Sie Bilder für alle unterstützten Geräte (wie XS Max, XR) hinzufügen, da UIScreen.main.bounds ohne diese keinen richtigen Wert zurückgibt.

7
budidino

Swift 4 wiederverwendbar Erweiterung

    public extension UIDevice {

    public enum `Type` {
        case iPad
        case iPhone_unknown
        case iPhone_5_5S_5C
        case iPhone_6_6S_7_8
        case iPhone_6_6S_7_8_PLUS
        case iPhone_X_Xs
        case iPhone_Xs_Max
        case iPhone_Xr
    }

    public var hasHomeButton: Bool {
        switch type {
        case .iPhone_X_Xs, .iPhone_Xr, .iPhone_Xs_Max:
            return false
        default:
            return true
        }
    }

    public var type: Type {
        if userInterfaceIdiom == .phone {
            switch UIScreen.main.nativeBounds.height {
            case 1136:
                return .iPhone_5_5S_5C
            case 1334:
                return .iPhone_6_6S_7_8
            case 1920, 2208:
                return .iPhone_6_6S_7_8_PLUS
            case 2436:
                return .iPhone_X_Xs
            case 2688:
                return .iPhone_Xs_Max
            case 1792:
                return .iPhone_Xr
            default:
                return .iPhone_unknown
            }
        }
        return .iPad
   }
}
6
ale_stro

Laut der Antwort von @saswanb ist dies eine Swift 4-Version:

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

Alle Antworten, die die Variable height verwenden, sind aus einem Grund nur die Hälfte der Geschichte. Wenn Sie dies überprüfen, wenn die Geräteorientierung landscapeLeft oder landscapeRight ist, schlägt die Prüfung fehl, da die height mit der width ausgelagert ist.

Deshalb sieht meine Lösung in Swift 4.0 so aus:

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

Sie sollten nicht davon ausgehen, dass das einzige Gerät, das Apple mit einer anderen UINavigationBar-Höhe freigibt, das iPhone X ist. Versuchen Sie, dieses Problem mit einer allgemeineren Lösung zu lösen. Wenn der Balken immer um 20 Pixel größer sein soll als die Standardhöhe, sollte der Code der Balkenhöhe um 20 Pixel erhöht werden, anstatt ihn auf 64 Pixel (44 Pixel + 20 Pixel) einzustellen.

4
IMcD23

Swift 3 + 4:

ohne dass ein Pixelwert für die Gerätegröße erforderlich ist

//UIApplication+SafeArea.Swift

extension UIApplication { 

    static var isDeviceWithSafeArea:Bool {

        if #available(iOS 11.0, *) {
            if let topPadding = shared.keyWindow?.safeAreaInsets.bottom,
                topPadding > 0 {
                return true
            }
        }

        return false
    }
}

Beispiel:

if UIApplication.isDeviceWithSafeArea {
     //e.g. change the frame size height of your UITabBar
}
4
Peter Kreinz
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
Kiran Sarvaiya
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0f)
3
alexander.pan

Normalerweise benötigt der Programmierer ihn, um ihn nach oben oder unten zu beschränken, damit diese Methoden helfen können

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
}

Für vor dem iPhone X geben diese Methoden Folgendes zurück: 0

Für iPhone X: 44 und 34 entsprechend

Dann fügen Sie diese Extras einfach zu den oberen oder unteren Randbedingungen hinzu

3
Andrey

Für diejenigen, die 2001px statt 2436px für die native Begrenzungshöhe erhalten (wie ich), liegt dies daran, dass Sie Ihre App mit einem älteren SDK vor iOS 11 (Xcode 8 statt Xcode 9) erstellt haben. Mit einem älteren SDK zeigt iOS die Apps "black boxed" auf dem iPhone X an, anstatt den Bildschirm Edge-to-Edge über die oberste "Sensorkerbe" hinaus zu erweitern. Dadurch wird die Bildschirmgröße reduziert, weshalb diese Eigenschaft 2001 statt 2436 zurückgegeben wird.

Die einfachste Lösung besteht darin, nur für beide Größen zu prüfen, ob Sie nur an der Geräteerkennung interessiert sind. Ich habe diese Methode zum Erkennen von FaceID verwendet, während mit einem älteren Xcode SDK erstellt wurde, in dem der ENUM-Wert nicht den biometrischen Typ angibt. In dieser Situation schien die Geräteerkennung anhand der Bildschirmhöhe der beste Weg zu sein, um zu wissen, ob das Gerät FaceID vs. TouchID hatte, ohne Xcode aktualisieren zu müssen.

3
Jon Summers
- (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
user6788419

Ich habe auf Ihre Antworten zu den Antworten von else eingegangen und die Erweiterung von Swift auf UIDevice vorgenommen. Ich mag Swift Enums und "alles in Ordnung" & atomisiert. Ich habe eine Lösung entwickelt, die sowohl auf dem Gerät als auch im Simulator funktioniert. 

Vorteile: - einfache Schnittstelle, Verwendung z. Mit UIDevice.current.isIPhoneX- UIDeviceModelType enum können Sie modellspezifische Funktionen und Konstanten, die Sie in Ihrer App verwenden möchten, problemlos erweitern, z. Eckenradius

Nachteil: - Es handelt sich um eine modellspezifische Lösung, nicht um eine Auflösung, z. Wenn Apple ein anderes Modell mit denselben Spezifikationen produziert, funktioniert dies nicht richtig und Sie müssen ein anderes Modell hinzufügen, damit dies funktioniert => Sie müssen Ihre App aktualisieren.

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
deathhorse

Verwenden Sie KEINE Bildschirmpixelgröße, da andere Lösungen vorgeschlagen haben. Dies ist schlecht, da dies zu falschen Ergebnissen für zukünftige Geräte führen kann. funktioniert nicht, wenn UIWindow noch nicht gerendert ist (AppDelegate), funktioniert nicht in Querformat-Apps und kann im Simulator fehlschlagen, wenn die Skalierung festgelegt ist.

Ich habe stattdessen ein Makro für diesen Zweck erstellt. Es ist sehr einfach zu verwenden und setzt Hardware-Flags ein, um die oben genannten Probleme zu vermeiden.

Bearbeiten: Aktualisiert zur Unterstützung von iPhoneX, iPhone XS, iPhoneXR, iPhoneXS Max


Benutzen:

if (IS_DEVICE_IPHONEX) {
    //do stuff
}

Ja, wirklich. 


Makro:

Kopieren Sie dies einfach an einer beliebigen Stelle, ich bevorzuge das Ende meiner .h-Datei nach @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]);\
})()\
)
2
Albert Renshaw

Ich stütze mich auf die Höhe der Statusleiste, um herauszufinden, ob es sich um ein iPhone X handelt:

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

Dies ist für die Anwendung un Portrait. Sie können die Größe auch entsprechend der Ausrichtung des Geräts überprüfen. Auf anderen iPhones ist die Statusleiste möglicherweise ausgeblendet, sodass die Bildhöhe 0 ist. Auf dem iPhone X wird die Statusleiste nie ausgeblendet.

2
Tiois

Ich benutzte Peter Kreinz 'Code (weil es sauber war und tat, was ich brauchte), aber dann wurde mir klar, dass es funktioniert, wenn sich das Gerät im Porträt befindet (da die obere Polsterung offensichtlich oben ist) .__ Eine Erweiterung erstellt, die alle Ausrichtungen mit den entsprechenden Auffüllungen berücksichtigt, ohne die Bildschirmgröße zu ändern:

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

Und auf Ihrer Anrufseite können Sie einfach:

let res = UIDevice.current.isIphoneX
2
rgkobashi

Alternativ können Sie ' DeviceKit ' pod ..__ auschecken. Nach der Installation müssen Sie lediglich das Gerät überprüfen:

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

Ich musste das gleiche Problem kürzlich lösen. Und obwohl diese Frage definitiv beantwortet ist ("Nein"), kann dies anderen helfen, die ein spezifisches Layout für das iPhone X benötigen. 

Ich war nicht wirklich daran interessiert, ob das Gerät ein iPhone X war. Ich interessierte mich dafür, ob das Gerät ein gekerbtes Display hatte.

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
}

Sie könnten auch eine Variable hasOnScreenHomeIndicator nach denselben Zeilen schreiben (überprüfen Sie jedoch den unteren sicheren Bereich, vielleicht?).

Im obigen Abschnitt wird meine Erweiterung auf UIView verwendet, um unter iOS 10 und früheren Versionen bequem auf die sicheren Bereiche zuzugreifen. 

@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
simeon

Es gibt mehrere Gründe, um wissen zu wollen, was das Gerät ist.

  1. Sie können die Höhe und Breite des Geräts überprüfen. Dies ist nützlich für das Layout, aber normalerweise möchten Sie dies nicht, wenn Sie das genaue Gerät kennen möchten.

  2. Zu Layoutzwecken können Sie auch UIView.safeAreaInsets verwenden.

  3. Wenn Sie den Gerätenamen anzeigen möchten, um ihn z. B. zu Diagnosezwecken in eine E-Mail aufzunehmen, nachdem Sie das Gerätemodell mithilfe von sysctl () abgerufen haben, können Sie das Äquivalent dazu verwenden, um den Namen anzugeben:

    $ curl http://appledevicenames.com/devices/iPhone10,6
    
    iPhone X
    
0
Hwee-Boon Yar

Ich denke, Apple möchte nicht, dass wir manuell prüfen, ob das Gerät "Notch" oder "Home Indicator" hat aber der Code, der funktioniert, ist:

-(BOOL)hasTopNotch{

    if (@available(iOS 11.0, *)) {

        float max_safe_area_inset = MAX(MAX([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top, [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.right),MAX([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.bottom, [[[UIApplication sharedApplication] delegate] window].safeAreaInsets.left));

        return max_safe_area_inset >= 44.0;

    }

    return  NO;

}

-(BOOL)hasHomeIndicator{

    if (@available(iOS 11.0, *)) {

        int iNumberSafeInsetsEqualZero = 0;

        if([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top == 0.0)iNumberSafeInsetsEqualZero++;
        if([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.right == 0.0)iNumberSafeInsetsEqualZero++;
        if([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.bottom == 0.0)iNumberSafeInsetsEqualZero++;
        if([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.left == 0.0)iNumberSafeInsetsEqualZero++;

        return iNumberSafeInsetsEqualZero <= 2;

    }

    return  NO;

}

Einige der anderen Beiträge funktionieren nicht. Zum Beispiel hat das iPhone 6S mit "In-Call-Statusleiste" (grüne Leiste) im Hochformatmodus einen großen sicheren oberen Bereich. Mit meinem Code werden alle Fälle aufgenommen ( auch wenn das Gerät im Hoch- oder Querformat startet )

0
BIOS-K

Der beste und einfachste Weg, um herauszufinden, ob das Gerät ein iPhone X ist,

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

Und die Kennung ist entweder "iPhone10,3" oder "iPhone10,6" für iPhone X.

0
satheeshwaran

Nur in Portrait verwende ich die Breite und Höhe des Rahmens der Ansicht, um Folgendes zu überprüfen:

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

}

Die Abmessungen des Hochformatbildschirms sind hier aufgeführt

 enter image description here

0
Lance Samaria

Mit der Veröffentlichung von iOS 12 können Geräte wie das iPhone X in diese Kategorie fallen. 

extension UIDevice {
    var isPortrait: Bool {

       return UIDeviceOrientationIsPortrait(orientation) ||
      UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)

  }

   var isDeviceWith_XShape : Bool {

    if self.userInterfaceIdiom == .phone {

        if isPortrait
        {
            switch UIScreen.main.nativeBounds.height {

            case 2436,2688,1792:
                print("iPhone X, Xs, Xr, Xs Max")
                return true
            default:
                print("Any other device")
                return false
            }
        }
        else
        {
            switch UIScreen.main.nativeBounds.width {

            case 2436,2688,1792:
                print("iPhone X, Xs, Xr, Xs Max")
                return true
            default:
                print("Any other device")
                return false
            }
        }


    }
    else
    {
        return false
    }

}`
0
dev_shanghai

Für eine schnelle Lösung gefällt mir Folgendes:

let var:CGFloat = (UIDevice.current.userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436) ? <iPhoneX> : <AllOthers>
0
Andres Canella

Erkennen eines der Geräte mithilfe einfacher Methoden. Wie unten,

func isPhoneDevice() -> Bool {
    return UIDevice.current.userInterfaceIdiom == .phone
}

func isDeviceIPad() -> Bool {
    return UIDevice.current.userInterfaceIdiom == .pad
}

func isPadProDevice() -> Bool {
    let SCREEN_WIDTH: CGFloat = UIScreen.main.bounds.size.width
    let SCREEN_HEIGHT: CGFloat = UIScreen.main.bounds.size.height
    let SCREEN_MAX_LENGTH: CGFloat = fmax(SCREEN_WIDTH, SCREEN_HEIGHT)

    return UIDevice.current.userInterfaceIdiom == .pad && SCREEN_MAX_LENGTH == 1366.0
}

func isPhoneXandXSDevice() -> Bool {
    let SCREEN_WIDTH = CGFloat(UIScreen.main.bounds.size.width)
    let SCREEN_HEIGHT = CGFloat(UIScreen.main.bounds.size.height)
    let SCREEN_MAX_LENGTH: CGFloat = fmax(SCREEN_WIDTH, SCREEN_HEIGHT)

    return UIDevice.current.userInterfaceIdiom == .phone && SCREEN_MAX_LENGTH == 812.0
}

func isPhoneXSMaxandXRDevice() -> Bool {
    let SCREEN_WIDTH = CGFloat(UIScreen.main.bounds.size.width)
    let SCREEN_HEIGHT = CGFloat(UIScreen.main.bounds.size.height)
    let SCREEN_MAX_LENGTH: CGFloat = fmax(SCREEN_WIDTH, SCREEN_HEIGHT)

    return UIDevice.current.userInterfaceIdiom == .phone && SCREEN_MAX_LENGTH == 896.0
}

und rufen Sie so an,

if isPhoneDevice() {
     // Your code
}
0
User558