Wykryj, czy urządzenie jest iPhone X

Moja aplikacja na iOS używa niestandardowej wysokości dla UINavigationBar, co prowadzi do pewnych problemów na nowym iPhone X.

Czy ktoś już wie jakniezawodnie wykrywać programowo (w Objective-C) czy aplikacja działa na iPhonie X?

EDIT:

Oczywiście sprawdzanie rozmiaru ekranu jest możliwe, jednak zastanawiam się, czy istnieje jakaś metoda "wbudowana", taka jak TARGET_OS_IPHONE do wykrywania iOS...

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

Edytuj 2:

Nie sądzę, że moje pytanie jest duplikatem połączonego pytania. Oczywiście istnieją metody "mierzenia" różnych właściwości bieżącego urządzenia i wykorzystywania wyników do decydowania, które urządzenie jest używane. Jednak nie o to chodziło w moim pytaniu, co starałem się podkreślić w mojej pierwszej edycji.

Prawdziwe pytanie brzmi: "czy możliwe jest bezpośrednie wykrycie, czy obecne urządzenie to iPhone X (np. przez jakąś funkcję SDK), Czy muszę używać pomiarów pośrednich"?

Przez odpowiedzi udzielone tak far, zakładam, że odpowiedź brzmi: "Nie, Nie ma bezpośrednich metod. Pomiary są drogą do zrobienia".

Author: Kiran Sarvaiya, 2017-09-13

30 answers

Na podstawie Twojego pytania, odpowiedź brzmi Nie, Nie ma bezpośrednich metod, aby uzyskać więcej informacji, możesz uzyskać informacje z here 1 i here 2

Jeśli chcesz wykryć iPhone X Wysokość użyj 2436px

Rozmiar i rozdzielczość ekranu urządzenia

Tutaj wpisz opis obrazka

Rozmiary i orientacje ekranu urządzenia

Tutaj wpisz opis obrazka

Swift 3 i above

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

Na podstawie Twojego pytania jak poniżej

Lub użyj screenSize.wysokość jako float 812.0f nie 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");
}

Więcej informacji można uzyskać tutaj

Swift

Lub wykryć za pomocą 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;
}

aktualizacja

Nie używaj userInterfaceIdiom właściwość do identyfikacji typu urządzenia, jak wyjaśnia dokumentacja Apple,

Dla aplikacji uniwersalnych, można użyć tej właściwości, aby dostosować zachowanie aplikacji do określonego typu urządzenia. Na przykład urządzenia iPhone i iPad mają różne rozmiary ekranu, więc możesz tworzyć różne widoki i kontrolki w zależności od typu bieżącego urządzenia.

To znaczy, ta właściwość jest po prostu używana do identyfikacji stylu widoku uruchomionej aplikacji. Jednak aplikacja iPhone (Nie uniwersalna) może być zainstalowana w urządzeniu iPad za pośrednictwem App store, w takim przypadku interfejs użytkownika zwróci również interfejs użytkownika.

Dobrym sposobem jest uzyskanie nazwy Maszyny przez uname, sprawdź ten wątek dla szczegółów.

 225
Author: Anbu.karthik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-05 09:55:31

[1]} kolejna możliwość, która działa na iOS 11 i iOS 12, ponieważ iPhone X jest jedynym z wycięciem na górze i wstawką 44. To właśnie tutaj wykrywam:

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

I oczywiście, jeśli jesteś w orientacji poziomej, może być konieczne sprawdzenie lewej i prawej strefy bezpieczeństwa.

Edit: _window jest UIWindow AppDelegate, gdzie to sprawdzenie odbywa się w aplikacji didFinishLaunchingWithOptions.

Odpowiedź zaktualizowana dla iOS 12 do sprawdzenia jeśli top > 20 zamiast top > 0.

 77
Author: saswanb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 16:19:53

Możesz zrobić tak, aby wykryć iPhone x urządzenie zgodnie z wymiarem.

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     
}

Tutaj wpisz opis obrazka

Ale ,

To nie jest wystarczający sposób. Co jeśli Apple ogłosiło następny iPhone o tym samym wymiarze iPhone X. najlepszym sposobem jest użycie ciągu sprzętowego do wykrycia urządzenia.

Dla nowszych urządzeń ciąg sprzętowy jest jak poniżej.

IPhone 8 - iPhone10, 1 lub iPhone 10,4

IPhone 8 Plus - iPhone10,2 lub iPhone 10,5

IPhone X - iPhone10,3 lub iPhone10,6

 41
Author: Jaydeep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 06:44:36

Wykonasz różne detekcje iPhone ' a X w zależności od rzeczywistej potrzeby.

Do radzenia sobie z najwyższym nacięciem (statusbar, navbar) itp.

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
}

Do obsługi dolnego wskaźnika głównego (tabbara) itp.

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
}

Dla rozmiaru tła, funkcji pełnoekranowych itp.

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

Uwaga: ewentualnie wymieszać z UIDevice.current.userInterfaceIdiom == .phone
Uwaga: ta metoda wymaga posiadania storyboardu LaunchScreen lub WŁAŚCIWEGO LaunchImages

Dla tła, przewijanie funkcje itp.

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
}

Uwaga: ta metoda wymaga posiadania storyboardu LaunchScreen lub odpowiednich LaunchImages

Do analizy, statystyk, śledzenia itp.

Pobierz identyfikator Maszyny i porównaj go z udokumentowanymi wartościami:

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"
}
Aby włączyć symulator jako poprawny iPhone X do analizy:
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"
}
Aby włączyć iPhone XS, XS Max i XR, po prostu poszukaj modeli zaczynających się od "iPhone11":
return model == "iPhone10,3" || model == "iPhone10,6" || model.starts(with: "iPhone11,")

Do obsługi 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
}
 39
Author: Cœur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-13 03:29:37

Sprawdź model urządzenia / nazwę Maszyny , nie używaj bezpośrednio liczby punktów / pikseli w kodzie, to hard code!

#import <sys/utsname.h>

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

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

Wynik:

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

Zobacz tę odpowiedź .

Pełna implementacja kodu:

#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
Author: Itachi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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].rozmiar.wysokość = = 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"]

Uwaga: - uważaj, działa dobrze tylko dla orientacji portretowej

 23
Author: Jagveer Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 14:27:03

Po przyjrzeniu się wszystkim odpowiedziom, tak się skończyło:

Solution (SWIFT 4.1 compatible)

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

Użyj

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

Uwaga

Pre Swift 4.1 możesz sprawdzić, czy aplikacja działa na symulatorze jak tak:

TARGET_OS_SIMULATOR != 0

Od wersji Swift 4.1 i nowszych możesz sprawdzić, czy aplikacja działa na symulatorze, używając Target environment platform condition :

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

(starsza metoda nadal będzie działać, ale ta nowa metoda jest bardziej future proof)

 22
Author: Cloud9999Strife,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 06:54:52

Wszystkie te odpowiedzi oparte na wymiarach są podatne na nieprawidłowe zachowanie na przyszłych urządzeniach. Będą działać dzisiaj, ale co jeśli w przyszłym roku będzie iPhone tego samego rozmiaru, ale ma aparat itp. pod szybą, żeby nie było "nacięć"?"Jeśli jedyną opcją jest aktualizacja aplikacji, jest to słabe rozwiązanie dla Ciebie i Twoich klientów.

Możesz również sprawdzić ciąg modelu sprzętowego typu "iPhone10, 1", ale to problematyczne, ponieważ czasami Apple wypuszcza inny model numery dla różnych przewoźników na całym świecie.

Poprawnym podejściem jest przeprojektowanie górnego układu lub rozwiązanie problemów z niestandardową wysokością paska nawigacyjnego (na tym bym się skupił). Ale jeśli zdecydujesz się nie robić żadnej z tych rzeczy, zdaj sobie sprawę, że cokolwiek robisz, jest hack, aby to zadziałało dzisiaj, i będziesz musiał to poprawić w pewnym momencie, być może wiele razy, aby hacki działały.

 17
Author: clarus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 02:29:57

Tak, to możliwe. Pobierz rozszerzenie UIDevice-Hardware (lub zainstaluj przez Cocoapod 'UIDevice-Hardware'), a następnie użyj:

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

Zauważ, że to nie zadziała w symulatorze, tylko na rzeczywistym urządzeniu.

 10
Author: Hendrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-01 20:32:05

SWIFT 4 + Odpowiedz

IPhone X, XR, XS, XSMAX:

Uwaga: potrzebujesz prawdziwego urządzenia do testu

Odniesienie

 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
Author: Jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 10:15:50

Według odpowiedzi @saswanb, jest to wersja Swift 4:

var iphoneX = false
if #available(iOS 11.0, *) {
    if ((UIApplication.shared.keyWindow?.safeAreaInsets.top)! > CGFloat(0.0)) {
        iphoneX = true
    }
}
 6
Author: MattOZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 14:44:09

Wiem, że to tylko szybkie rozwiązanie, ale może komuś pomóc.

Mam globals.swift w każdym projekcie i jedną z rzeczy, które zawsze dodaję, jest DeviceType, aby łatwo wykryć urządzenie użytkownika:

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
}

Następnie użyć go:

if DeviceType.iPhoneX {
  print("This executes only on iPhoneX")
}
 6
Author: budidino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-09 09:33:22

Nie powinieneś zakładać, że jedynym urządzeniem, które Apple wyda z inną wysokością UINavigationBar będzie iPhone X. spróbuj rozwiązać ten problem używając bardziej ogólnego rozwiązania. Jeśli chcesz, aby pasek był zawsze o 20px większy niż jego domyślna wysokość, kod powinien dodać 20px do wysokości paska, zamiast ustawiać go na 64px(44px + 20px).

 4
Author: IMcD23,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-18 23:57:45

Wszystkie odpowiedzi, które używają height są tylko połową części historii z jednego powodu. Jeśli masz zamiar sprawdzić w ten sposób, gdy orientacja urządzenia jest landscapeLeft lub landscapeRight, sprawdzenie nie powiedzie się, ponieważ height jest zamienione na width.

Dlatego moje rozwiązanie wygląda tak w 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
Author: DevAndArtist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Kiran Sarvaiya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 06:04:33

Swift 3 + 4:

Bez potrzeby podawania wartości piksela wielkości urządzenia

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

Przykład:

if UIApplication.isDeviceWithSafeArea {
     //e.g. change the frame size height of your UITabBar
}
 4
Author: Peter Kreinz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: alexander.pan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: user6788419,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-19 11:52:39

Zwykle programista potrzebuje go do ograniczenia do góry lub do dołu, więc te metody mogą pomóc

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
}

For before iPhone X these methods return: 0

Dla iPhone X: 44 i 34 odpowiednio

Następnie po prostu dodaj te dodatki do górnej lub dolnej krawędzi

 3
Author: Andrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-17 12:00:31

Dla tych, którzy otrzymują 2001px zamiast 2436px dla wysokości natywnych granic (jak ja), to dlatego, że zbudowałeś swoją aplikację ze starszym SDK, przed iOS 11 (Xcode 8 zamiast Xcode 9). Dzięki starszemu zestawowi SDK iOS wyświetli aplikacje " czarne pudełka "na iPhone X zamiast rozszerzać ekran od krawędzi do krawędzi, poza górny"wycięcie czujnika". Zmniejsza to rozmiar ekranu, dlatego właściwość zwraca 2001 zamiast 2436.

Najprostszym rozwiązaniem jest sprawdzenie obu rozmiarów, jeśli są zainteresowani tylko wykrywaniem urządzeń. Użyłem tej metody do wykrywania FaceID podczas budowania ze starszym Xcode SDK, który nie ma wartości ENUM określającej Typ biometryczny. W tej sytuacji wykrywanie urządzenia za pomocą wysokości ekranu wydawało się najlepszym sposobem, aby wiedzieć, czy urządzenie miało FaceID vs TouchID bez konieczności aktualizacji Xcode.

 3
Author: Jon Summers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-14 18:31:35

Opracowałem Twoje odpowiedzi na else i zrobiłem szybkie rozszerzenie na UIDevice. Lubię szybkie wyliczenia i "wszystko w porządku" i rozpylanie. Stworzyłem rozwiązanie, które działa zarówno na urządzeniu, jak i symulatorze.

Zalety: - prosty interfejs, użycie np. UIDevice.current.isIPhoneX - UIDeviceModelType enum daje możliwość łatwego rozszerzenia funkcji i stałych specyficznych dla modelu, które chcesz wykorzystać w swojej aplikacji, np.]}

: - jest to rozwiązanie specyficzne dla modelu, nie specyficzne dla rozdzielczości - np. jeśli Apple wyprodukuje kolejny model z tymi samymi specyfikacjami, to nie będzie działać poprawnie i musisz dodać inny model, aby to działało => musisz zaktualizować aplikację.

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
Author: deathhorse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-08 13:45:06

[[2]}polegam na wysokości Ramki paska stanu, aby wykryć, czy jest to iPhone X:

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

To jest dla aplikacji un portrait. Możesz również sprawdzić rozmiar zgodnie z orientacją urządzenia. Również na innych iPhone ' ach pasek stanu może być ukryty, więc wysokość ramki wynosi 0. W telefonie iPhone X pasek stanu nigdy nie jest ukryty.

 2
Author: Tiois,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 17:39:35

Używałem kodu Petera Kreinza (ponieważ był czysty i zrobił to, co potrzebowałem) , ale potem zdałem sobie sprawę, że działa tylko wtedy, gdy urządzenie jest na portrecie (ponieważ Top padding będzie na górze, oczywiście) Dlatego stworzyłem rozszerzenie do obsługi wszystkich orientacji z odpowiednimi paddingami, bez przenoszenia na rozmiar ekranu:

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

A na twojej stronie po prostu:

let res = UIDevice.current.isIphoneX
 2
Author: rgkobashi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 08:32:53

Ostatnio musiałem rozwiązać ten sam problem. I chociaż to pytanie jest definitywnie odpowiedział ("nie"), może to pomóc innym, którzy potrzebują iPhone X konkretnego zachowania układu.

Nie interesowało mnie, czy urządzenie to iPhone X. interesowało mnie, czy urządzenie ma karbowany wyświetlacz.
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
}

Możesz również napisać zmienną hasOnScreenHomeIndicator wzdłuż tych samych linii (chociaż sprawdź dolny obszar bezpieczny, może?).

Powyższe używa mojego rozszerzenia na UIView dla wygodnego dostępu do wstawek obszaru bezpiecznego w systemie iOS 10 i wcześniejszych.

@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
Author: simeon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-01 03:32:11

Alternatywnie możesz sprawdzić pod' DeviceKit'. Po zainstalowaniu, wszystko, co musisz zrobić, aby sprawdzić urządzenie, to:

import DeviceKit
let device = Device()
if device == .iPhoneX {
  // place your code here
}
 1
Author: Islombek Hasanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-04 16:57:34

Nie używaj rozmiaru piksela ekranu, jak sugerowały inne rozwiązania, jest to złe, ponieważ może powodować fałszywe alarmy dla przyszłych urządzeń; nie będzie działać, jeśli UIWindow jeszcze nie renderował (AppDelegate), nie będzie działać w aplikacjach krajobrazowych i może nie działać na symulatorze, jeśli skala jest ustawiona.

Zamiast tego zrobiłem makro do tego celu, jest bardzo łatwe w użyciu i opiera się na flagach sprzętowych, aby zapobiec wyżej wymienionym problemom.

Edytuj: Zaktualizowano obsługę iPhoneX, iPhone XS, iphonexr, iPhoneXS Max

Do Użycia:

if (IS_DEVICE_IPHONEX) {
    //do stuff
}
Tak, naprawdę.

Makro:

Po prostu skopiuj wklej to gdziekolwiek, wolę sam dół mojego .plik h po @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
Author: Albert Renshaw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-26 20:48:38

Istnieje kilka powodów, dla których warto wiedzieć, czym jest urządzenie.

  1. Możesz sprawdzić wysokość (i szerokość) urządzenia. Jest to przydatne dla układu, ale zazwyczaj nie chcesz tego robić, jeśli chcesz znać dokładne urządzenie.

  2. Do celów układu można również użyć UIView.safeAreaInsets.

  3. Jeśli chcesz wyświetlić nazwę urządzenia, na przykład, która ma być zawarta w wiadomości e-mail w celach diagnostycznych, po pobraniu modelu urządzenia za pomocą sysctl (), możesz użyć odpowiednik tej nazwy:

    $ curl http://appledevicenames.com/devices/iPhone10,6
    
    iPhone X
    
 0
Author: Hwee-Boon Yar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-14 15:48:31

Na szybką naprawę, podoba mi się to:

let var:CGFloat = (UIDevice.current.userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height == 2436) ? <iPhoneX> : <AllOthers>
 0
Author: Andres Canella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 23:09:43

Najlepszym i najłatwiejszym sposobem wykrycia, czy urządzenie jest iPhone X,

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)))}
W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone 'a X. W przypadku iPhone' a X. W przypadku iPhone ' a X.]}
 0
Author: satheeshwaran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-29 09:22:46

W tylko portret używam szerokości i wysokości ramki widoku, aby sprawdzić:

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

}

Wymiary ekranu portretowego są wymienione tutaj

Tutaj wpisz opis obrazka

 0
Author: Lance Samaria,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-16 01:01:45