पता लगाएँ कि क्या डिवाइस iPhone X है


262

मेरा iOS ऐप के लिए एक कस्टम ऊंचाई का उपयोग करता है UINavigationBar जिसके लिए नए iPhone X पर कुछ समस्याएं आती हैं।

क्या कोई व्यक्ति पहले से ही पता लगा सकता है कि iPhone X पर ऐप चल रहा है, तो प्रोग्रामेटिक रूप से (ऑब्जेक्टिव-सी) में विश्वसनीय कैसे पता करें ?

संपादित करें:

बेशक, स्क्रीन के आकार की जांच करना संभव है, हालांकि, मुझे आश्चर्य है कि क्या TARGET_OS_IPHONEआईओएस का पता लगाने के लिए कुछ "बिल्ड" विधि है ...

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

संपादित करें 2:

मुझे नहीं लगता, कि मेरा प्रश्न लिंक किए गए प्रश्न का डुप्लिकेट है। बेशक, मौजूदा डिवाइस के विभिन्न गुणों को "मापने" के तरीके हैं और परिणामों का उपयोग करने के लिए यह तय करने के लिए कि किस डिवाइस का उपयोग किया जाता है। हालाँकि, यह मेरे प्रश्न का वास्तविक बिंदु नहीं था क्योंकि मैंने अपने पहले संपादन में जोर देने की कोशिश की थी।

वास्तविक प्रश्न यह है: "क्या वर्तमान डिवाइस iPhone X (उदाहरण के लिए कुछ SDK फीचर) है या क्या मुझे अप्रत्यक्ष माप का उपयोग करना है" ?

अब तक दिए गए उत्तरों से, मैं मानता हूं कि उत्तर "नहीं है, कोई सीधा तरीका नहीं है। माप ही जाने का रास्ता है"।


iPhone X में स्क्रीन रिज़ॉल्यूशन दूसरों से अलग है।
एल टमाटर

2
हां, जैसा कि मैंने अपने संपादन में उल्लेख किया है कि स्क्रीन आकार की जांच करना संभव है। हालांकि सवाल यह है कि अगर डिवाइस के प्रकार को "इनडायरेक्ट" मापों के बजाय क्वेरी करने के लिए "डायरेक्ट" विधि है ...
आंद्रेई हेरफोर्ड

3
लेखक केवल डिवाइस प्रकार प्राप्त करना चाहता है, स्क्रीन रिज़ॉल्यूशन नहीं। सीधे मशीन का नाम क्यों नहीं जांचा? @lubilis सही है।
इटाची

2
Apple द्वारा सुझाए गए अनुसार आप केवल सुरक्षित क्षेत्र गाइड का उपयोग क्यों नहीं करते हैं?
१२:१२

4
महत्वपूर्ण, भविष्य के देवता: इस उपयोग स्क्रीन ऊंचाई का पता न लगाएं क्योंकि वर्तमान शीर्ष समाधान सुझाते हैं, यह बुरा है क्योंकि इससे भविष्य के उपकरणों के लिए झूठी सकारात्मकता हो सकती है; यदि UIWindow ने अभी तक रेंडर नहीं किया है (जैसे आपके AppDelegate init फ़ंक्शन), तो लैंडस्केप ऐप्स में काम नहीं करेगा, और स्केल सेट होने पर सिम्युलेटर पर विफल हो सकता है। कभी इस तरह से चीजों के लिए जादू की संख्या का उपयोग करें! आप सफलता की गारंटी के लिए हार्डवेयर झंडे की जाँच कर सकते हैं जैसे मैंने यहाँ किया है: stackoverflow.com/a/51511947/2057171
अल्बर्ट रेनशॉ

जवाबों:


383

आपके प्रश्न के आधार पर, उत्तर नहीं है। कोई प्रत्यक्ष तरीके नहीं हैं। अधिक जानकारी के लिए आप यहाँ जानकारी प्राप्त कर सकते हैं:

तथा

IPhone X की ऊंचाई 2436 px है

से डिवाइस स्क्रीन आकार और संकल्प :

यहां छवि विवरण दर्ज करें

से डिवाइस स्क्रीन आकार तथा ऑरिएंटेशन :

यहां छवि विवरण दर्ज करें

स्विफ्ट 3 और बाद में :

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/11 Pro")

        case 2688:
            print("iPhone XS Max/11 Pro Max")

        case 1792:
            print("iPhone XR/ 11 ")

        default:
            print("Unknown")
        }
    }

उद्देश्य-सी :

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:
            print("iPhone X/XS/11 Pro");
             break;

        case 2688:
            print("iPhone XS Max/11 Pro Max");
             break;

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

अपने प्रश्न के आधार पर अनुसरण करें:

या screenSize.heightफ्लोट के रूप में उपयोग 812.0f नहीं 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");
    }

अधिक जानकारी के लिए आप iOS मानव इंटरफ़ेस दिशानिर्देशों में निम्नलिखित पृष्ठ का उल्लेख कर सकते हैं:

तीव्र :

के साथ का पता लगाएं topNotch:

यदि कोई iPhoneX का पता लगाने के लिए notch का उपयोग करने पर विचार कर रहा है, तो ध्यान रखें कि "परिदृश्य" सभी iPhones के लिए समान है।

var hasTopNotch: Bool {
    if #available(iOS 13.0,  *) {
        return UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.safeAreaInsets.top ?? 0 > 20
    }else{
     return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
    }

    return false
}

उद्देश्य-सी :

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

- (UIWindow*)keyWindow {
    UIWindow        *foundWindow = nil;
    NSArray         *windows = [[UIApplication sharedApplication]windows];
    for (UIWindow   *window in windows) {
        if (window.isKeyWindow) {
            foundWindow = window;
            break;
        }
    }
    return foundWindow;
}

अद्यतन :

userInterfaceIdiomडिवाइस प्रकार की पहचान करने के लिए संपत्ति का उपयोग न करें , क्योंकि प्रलेखन के लिए userInterfaceIdiom बताते हैं:

सार्वभौमिक अनुप्रयोगों के लिए, आप एक विशिष्ट प्रकार के डिवाइस के लिए अपने आवेदन के व्यवहार को दर्जी करने के लिए इस संपत्ति का उपयोग कर सकते हैं। उदाहरण के लिए, iPhone और iPad उपकरणों के स्क्रीन आकार अलग-अलग होते हैं, इसलिए आप वर्तमान डिवाइस के प्रकार के आधार पर अलग-अलग विचार और नियंत्रण बनाना चाह सकते हैं।

यानी यह प्रॉपर्टी सिर्फ रनिंग ऐप के व्यू स्टाइल को पहचानने के लिए इस्तेमाल की जाती है। हालाँकि, आईफ़ोन ऐप को ऐप स्टोर के माध्यम से आईपैड डिवाइस में स्थापित नहीं किया जा सकता हैuserInterfaceIdiom यह वापस आ जाएगाUIUserInterfaceIdiomPhone भी होगी।

सही तरीका मशीन नाम के माध्यम से प्राप्त करना है uname। विवरण के लिए निम्नलिखित की जाँच करें:


IPhone एक्स के संकल्प के अनुसार 2436 x 1125 पिक्सल है: iphonesoft.fr/2017/09/12/...
मेढाइ

1
@ मदी - iPhone X का रिज़ॉल्यूशन - 1125 x 2436 पिक्सेल (~ 458 ppi पिक्सेल घनत्व)
Anbu.Karthik

14
नहीं! IPhone डिवाइस (ब्रह्मांड नहीं) ऐप स्टोर के माध्यम से iPad डिवाइस में स्थापित किया जा सकता है, उस स्थिति में,userInterfaceIdiomवापसीUIUserInterfaceIdiomPhoneभी करेगा। यह उत्तर गलत है।
इताची

1
@ThreeCoins, लियो डबस के सुझाव के अनुसार प्लस उपकरणों के लिए अपना जवाब अपडेट करें। यह प्लस सिम्युलेटर पर काम करता है लेकिन डिवाइस पर नहीं।
हिरेन गुजराती

2
यह बुरा है क्योंकि इससे भविष्य के उपकरणों के लिए झूठी सकारात्मकता पैदा हो सकती है; अगर UIWindow ने अभी तक रेंडर नहीं किया है तो (AppDelegate) काम नहीं करेगा, लैंडस्केप ऐप में काम नहीं करेगा, और अगर स्केल सेट है तो सिम्युलेटर पर विफल हो सकता है। आप सफलता की गारंटी के लिए हार्डवेयर झंडे देख सकते हैं जैसे मैंने यहाँ किया है: stackoverflow.com/a/51511947/2057171
अल्बर्ट रेनशॉ

101

एक और संभावना, जो आईओएस 11 और आईओएस 12 पर काम करती है क्योंकि आईफोन एक्स शीर्ष पर एक पायदान और 44 के इनसेट के साथ एकमात्र है। यही वह है जो मैं वास्तव में यहां पता लगा रहा हूं:

उद्देश्य सी:

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

स्विफ्ट 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
}

और हां, अगर आपको लैंडस्केप ओरिएंटेशन में हैं तो आपको लेफ्ट और राइट सेफ़ एरिया की जांच करनी होगी।

संपादित करें: _window, AppDelegate का UIWindow है, जहां यह चेक एप्लिकेशन didFinishLaunchingWithOptions में किया जाता है।

IOS 12 के लिए उत्तर दिया गया है कि जाँच करें कि शीर्ष> 0 के बजाय शीर्ष> 24 है या नहीं।

संपादित करें: सिम्युलेटर में आप हार्डवेयर, टॉगल इन-कॉल स्टेटस बार पर जा सकते हैं। ऐसा करने से मुझे पता चलता है कि आईओएस 11 पर iPhone X पर स्टेटस बार की ऊंचाई नहीं बदलती है या कॉल करते समय iPhone XS iOS 12 दिखाई देता है। वह सभी परिवर्तन समय आइकन है, जिसे दोनों मामलों में, हरे रंग की पृष्ठभूमि मिलती है। यहाँ एक तस्वीर है:

यहां छवि विवरण दर्ज करें


5
यदि किसी अन्य डिवाइस पर दिखाई दे रहा है, तो सुरक्षित क्षेत्र के इनसेट में स्टेटस बार की ऊंचाई होगी। यह जाँचने पर कि यह 0 है केवल आपको बताएगा कि क्या स्टेटस बार दिखाई दे रहा है, यदि डिवाइस iPhone X है तो नहीं।
IMcD23

3
"यह iPhone Xs या iPhone 11 में टूट सकता है ", कुक ने कहा।
इताची

11
मैंने if _window.safeAreaInsets != UIEdgeInsets.zeroकिसी भी उपकरण अभिविन्यास के लिए अनुमति देने के लिए थोड़ा और उपयोग को अनुकूलित किया है
फ्रेजर

2
यदि आप उपयोग नहीं करना चाहते हैं .top, safeAreaInsets.bottomतो iPhone X पर 34 और अन्य उपकरणों पर 0 होगा
blwinters

7
चेतावनी: इसका उपयोग न करें, यह iOS 12 पर टूट जाता है। यह भी दस्तावेज नहीं है कि इस मामले में UIWindow को क्या करना चाहिए। Openradar.appspot.com/42372793
Stepipete

73

वास्तविक जरूरत के आधार पर आप iPhone X के अलग-अलग प्रदर्शन करेंगे।

शीर्ष पायदान (स्थिति पट्टी, नावबार), आदि से निपटने के लिए।

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
}

नीचे दिए गए होम इंडिकेटर (टैब्बर), आदि से निपटने के लिए।

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
}

बैकग्राउंड साइज, फुलस्क्रीन फीचर्स आदि के लिए।

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

नोट: अंत में इसे UIDevice.current.userInterfaceIdiom == .phone
नोट के साथ मिलाएं : इस विधि के लिए एक लॉन्चस्क्रीन स्टोरीबोर्ड या उचित लॉन्चइमेज होना आवश्यक है

बैकग्राउंड रेशियो, स्क्रॉलिंग फीचर्स आदि के लिए।

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
}

नोट: इस विधि के लिए एक लॉन्चस्क्रीन स्टोरीबोर्ड या उचित LaunchImages होना आवश्यक है

विश्लेषिकी, सांख्यिकी, ट्रैकिंग, आदि के लिए

मशीन पहचानकर्ता प्राप्त करें और इसकी तुलना दस्तावेजित मूल्यों से करें:

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

सिम्युलेटर को अपने विश्लेषण में एक मान्य iPhone X के रूप में शामिल करें:

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

IPhone XS, XS Max और XR को शामिल करने के लिए, बस "iPhone11," से शुरू होने वाले मॉडल देखें:

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

फेसआईडी समर्थन के लिए

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

मैं उम्मीद कर रहा था कि return LAContext().biometryType == .typeFaceIDउपयोगकर्ता काम करने से इनकार कर दिया था तो भी काम करेगा ।Policy, लेकिन यह मेरे लिए काम नहीं करता है, यह अभी भी लौटता है.none
जेरेमी

खैर @Jeremy, यह एक प्रलेखित व्यवहार है, Apple गोपनीयता नीति का परिणाम है। इसलिए विधि के ऊपर टिप्पणी।
Cœur

आह, मैंने आपकी टिप्पणी की गलत व्याख्या की। मैंने सोचा था कि आप का उपयोग कर सकते हैं CanPvaluatePolicy विफल हो सकता है, इसलिए इसके बजाय निम्नलिखित का उपयोग करें। मुझे यह थोड़ा अजीब लगता है कि आपको यह जांचने की अनुमति है कि क्या डिवाइस में फेस आईडी है जब तक उपयोगकर्ता टॉगल का जवाब नहीं देता है और फिर आप अब और भी नहीं देख सकते हैं। सेटिंग्स में जाने और फेस आईडी को टॉगल करने के लिए मुझे एक उपयोगी त्रुटि संदेश कैसे देना चाहिए?
जेरेमी

@ जेरेमी मेरे पास iPhone X नहीं है, इसलिए मुझे नहीं पता। हो सकता है कि आप ऊपर दिए गए मॉडल का उपयोग कर सकते हैं ( model == "iPhone10,3" || model == "iPhone10,6"), और यदि canUseFaceIDवह गलत है, तो इसका मतलब है कि यह उपयोगकर्ता द्वारा अस्वीकार कर दिया गया था।
कुआर

1
@MateoOlaya मेरे जवाब में कुछ भी Apple द्वारा अस्वीकार नहीं किया जाएगा: आप इसका उपयोग कर सकते हैं।
Cœur

42

IPhone X का पता लगाने के लिए आप ऐसा कर सकते हैं आयाम के अनुसार डिवाइस ।

तीव्र

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

उद्देश्य सी

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

यहां छवि विवरण दर्ज करें

परंतु ,

यह पर्याप्त तरीका नहीं है। क्या होगा अगर Apple ने iPhone X के समान आयाम के साथ अगले iPhone की घोषणा की। इसलिए डिवाइस का पता लगाने के लिए हार्डवेयर स्ट्रिंग का उपयोग करना सबसे अच्छा तरीका है।

नए डिवाइस के लिए हार्डवेयर स्ट्रिंग नीचे दी गई है।

iPhone 8 - iPhone10,1 या iPhone 10,4

iPhone 8 Plus - iPhone10,2 या iPhone 10,5

iPhone X - iPhone10,3 या iPhone10,6


2
आपको [UIDevice currentDevice]इसके बजाय का उपयोग करना चाहिए[[UIDevice alloc] init]
एस। मात्सपुरा

हार्डवेयर स्ट्रिंग के साथ एकमात्र समस्या यह है कि यह सिम्युलेटर पर काम नहीं करता है
quemeful

38

की जाँच करें डिवाइस मॉडल / मशीन नाम , अपने कोड में बात / पिक्सेल गणना का उपयोग नहीं करते सीधे, यह कठिन कोड और डिवाइस हार्डवेयर के लिए अर्थहीन, डिवाइस मॉडल उपकरण का प्रकार से मिलान करने के लिए केवल एक अद्वितीय पहचानकर्ता है

#import <sys/utsname.h>

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

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

परिणाम:

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

इस उत्तर को देखें ।

पूर्ण कोड कार्यान्वयन:

#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)
{
    NSArray<NSString *> *notchiModels = @[
        @"iPhone10,3", @"iPhone10,6", // iPhone X
        @"iPhone11,2", @"iPhone11,4", @"iPhone11,6", // iPhone XS (Max)
        @"iPhone11,8", // iPhone XR
        @"iPhone12,1", @"iPhone12,3", @"iPhone12,5", // iPhone 11 (Pro (Max))
    ];

    return [notchiModels containsObject:GetDeviceModel()];
}

1
उत्कृष्ट उत्तर चूंकि यह सिम्युलेटर को सही ढंग से संभालता है। कृपया "पूर्ण कोड" अनुभाग में #import लाइन जोड़ें। मुझे अपने पहले प्रयास में वह (कॉपी / पेस्ट) याद आया।
मपिसोट

1
यह मेरी पसंदीदा विधि है। डिवाइस मॉडल स्ट्रिंग्स की पूरी सूची के लिए इस विकी को देखें । साइड कमेंट के रूप में, @ "iphone10,3" को हार्ड कोड के रूप में भी देखा जा सकता है।
यवेसलबर्ग

1
@YvesLeBorg हाँ, यह वास्तव में एक महत्वपूर्ण विवादास्पद मुद्दा है। हार्डवेयर मॉडल स्ट्रिंग में डिवाइस के स्क्रीन बिंदुओं की तुलना में एक विशिष्ट पहचानकर्ता है, मुझे लगता है। आम तौर पर, इसका उपयोग डेटा आँकड़ों के लिए किया जाता है।
इटाची

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

IS_IPHONE_X (IS_IPHONE && [[UIScreen मेनस्क्रीन] सीमाएं] .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"]

नोट: - सावधान रहें, यह केवल पोर्ट्रेट ओरिएंटेशन के लिए ठीक काम करता है


2
सावधान रहें, यह केवल पोर्ट्रेट ओरिएंटेशन के लिए ठीक काम करता है
CFIFok

1
इसके लिए धन्यवाद। अच्छा काम करता है। लैंडस्केप मोड में आपको उन नंबरों को समायोजित करने की आवश्यकता है। लैंडस्केप मोड में iPhoneX की जादुई संख्या 375.0 है
pvella

कुछ iPhone प्लस / मैक्स / प्रो के nativeScaleसाथ उपयोग कर रहे हैं 3.0, है ना?
इटाची

24

सभी उत्तरों को देखने के बाद मैंने यही किया:

समाधान (स्विफ्ट 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
    }
}

उपयोग

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

ध्यान दें

प्री स्विफ्ट 4.1 आप जांच सकते हैं कि ऐप एक सिम्युलेटर पर चल रहा है या नहीं:

TARGET_OS_SIMULATOR != 0

स्विफ्ट 4.1 से और बाद में आप यह जांच सकते हैं कि ऐप टारगेट एनवायरनमेंट प्लेटफ़ॉर्म कंडीशन का उपयोग करके सिम्युलेटर पर चल रहा है या नहीं :

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

(पुरानी विधि अभी भी काम करेगी, लेकिन यह नई विधि अधिक भविष्य का प्रमाण है)


सेब इस के साथ ठीक हो जाएगा?
सुरजीत राजपूत

@ कमांडो 24 हां, मुझे इस कोड के कारण ऐप को अस्वीकार करने का कोई कारण नहीं दिखता है।
Cloud9999Strife

18

आयामों के आधार पर ये सभी उत्तर भविष्य के उपकरणों पर गलत व्यवहार के लिए अतिसंवेदनशील होते हैं। वे आज काम करेंगे, लेकिन क्या होगा अगर अगले साल एक iPhone है जो एक ही आकार का है, लेकिन कैमरे आदि के ग्लास के नीचे है, इसलिए "कोई निशान नहीं है?" यदि एकमात्र विकल्प ऐप को अपडेट करना है, तो यह आपके और आपके ग्राहकों के लिए एक खराब समाधान है।

आप "iPhone10,1" जैसे हार्डवेयर मॉडल स्ट्रिंग की भी जांच कर सकते हैं, लेकिन यह समस्याग्रस्त है क्योंकि कभी-कभी Apple दुनिया भर के विभिन्न वाहक के लिए अलग-अलग मॉडल नंबर जारी करता है।

सही दृष्टिकोण शीर्ष लेआउट को फिर से डिज़ाइन करना है, या कस्टम नेविगेशन बार ऊंचाई के साथ आपको होने वाली समस्याओं को हल करना है (यही वह है जो मैं ध्यान केंद्रित करूंगा)। लेकिन, यदि आप उन चीजों में से किसी एक को भी नहीं करने का निर्णय लेते हैं, तो महसूस करें कि आप जो कुछ भी कर रहे हैं वह आज काम करने के लिए एक हैक है , और आपको हैक रखने के लिए इसे किसी बिंदु पर, शायद कई बार सही करने की आवश्यकता होगी। काम कर रहे।


1
सही। एक धारणा को परिष्कृत करते हुए कि संख्या X सदैव A से एक होगी, वह संख्या X सदैव A होगी जब तक कि Y की स्थिति नहीं होगी जब वह B होगा, केवल गहरी खुदाई कर रहा होगा। Apple-नामांकित सुरक्षित क्षेत्र के आधार पर आकार, दूसरा अनुमान लगाने से नहीं।
टॉमी

2
मैं अगले iPhone के बारे में चिंता करूँगा जब यह वास्तव में वहाँ से बाहर होगा। मैं चाहता हूं कि मेरा ऐप TODAY पर काम करे।
वाहिद अमीरी

13

स्विफ्ट 4+ उत्तर

iPhone X, XR, XS, XSMAX, 11 प्रो, 11 प्रो मैक्स:

नोट: परीक्षण के लिए वास्तविक उपकरण की आवश्यकता है

संदर्भ

 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")
        case "iPhone12,3":
            print("iPhone 11 Pro")
        case "iPhone12,5":
            print("iPhone 11 Pro Max")
        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
    }
}

विधि 1 के लिए, आप फंक के बाहर "var विंडो" प्रॉपर्टी को हटा सकते हैं और इसके भीतर एक "लेट" स्थिर रखें (टाइप करें UIWindow, यानी वैकल्पिक नहीं)। मुझे स्टार्टअप पर यह उत्तर पसंद है, self.view.window nil हो सकता है, और UIApplication.sared.keyWindow वैसे ही nil हो सकता है, जबकि इस तरह से UIWindow बनाना हर बार काम करता है।
रोलरिक

11

IPhone 11 समर्थन के साथ SWIFT 4/5 पुन: प्रयोज्य विस्तार

    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_11_Pro_Max
        case iPhone_Xr_11
        case iPhone_11_Pro
    }

    public var hasHomeButton: Bool {
        switch type {
        case .iPhone_X_Xs, .iPhone_Xr_11, .iPhone_Xs_11_Pro_Max, .iPhone_11_Pro:
            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_11_Pro_Max
            case 1792: return .iPhone_Xr_11
            case 2426: return .iPhone_11_Pro
            default: return .iPhone_unknown
        }
        }
        return .iPad
   }
}

2
अच्छा विस्तार, लेकिन यहां सबसे उपयोगी हैUIDevice.current.hasHomeButton
वाइनरी

1
सार्वभौमिक ऐप के लिए उपकरणों का निर्धारण करने के लिए userInterfaceIdiom का उपयोग करना अच्छा है @ale_stro? अधिकांश लोग इसकी अनुशंसा नहीं करते हैं। क्या इसका उपयोग करने का कोई नुकसान है?
शकीर सैयद

10

हाँ यह संभव है। UIDevice- हार्डवेयर एक्सटेंशन डाउनलोड करें (या CocoaPod 'UIDevice-Hardware' के माध्यम से इंस्टॉल करें) और फिर उपयोग करें:

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

ध्यान दें कि यह सिम्युलेटर में काम नहीं करेगा, केवल वास्तविक डिवाइस पर।


सभी डिवाइस कोड यहाँ: iphonesoft.fr/2016/10/31/... iPhone10,5 और iPhone10,6: उदाहरण: iPhone एक्स
मेढाइ

हार्डवेयर तार से विकिपीडिया "iPhone10,3 और iPhone10,6" कहा। @ मदी
इताची

@ मेधी, ​​आप एक्सकोड ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIF‌​IER"]से वास्तविक मान प्राप्त करने के लिए सिम्युलेटर में उपयोग कर सकते हैं ।
कूर

9

@ Saswanb की प्रतिक्रिया के अनुसार, यह एक स्विफ्ट 4 संस्करण है:

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

सुरक्षित क्षेत्र के बाहर भी स्टेटस बार माना जाता है! तो यह झूठी सकारात्मक लौटेगा! यह अधिक होना चाहिए तब 20 पॉइंट (स्टेटसबार की ऊंचाई)। अगर डिवाइस iPhone Xs, R या Xs Max है तो यह भी सही है।
MQoder

कोड अच्छा काम करता है, लेकिन सावधान रहना: keyWindowहै nilजब तक मुख्य दृश्य नियंत्रक का आह्वान किया हैviewDidAppear
केसी

9

मुझे पता है कि यह केवल एक स्विफ्ट समाधान है, लेकिन यह किसी की मदद कर सकता है।

मेरे पास globals.swiftहर प्रोजेक्ट में है और एक चीज जो मैं हमेशा जोड़ता हूं, DeviceTypeवह है उपयोगकर्ता के डिवाइस का आसानी से पता लगाना:

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.maxWH == 896.0
  static var hasNotch: Bool {
    return iPhoneX || iPhoneXRMax
  }
}

फिर इसका उपयोग करने के लिए:

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

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

यदि आप LaunchImageअपनी परियोजना में उपयोग करते हैं, तो सभी समर्थित उपकरणों (जैसे कि मैक्स मैक्स, एक्सआर) के लिए चित्र जोड़ना सुनिश्चित करें क्योंकि UIScreen.main.boundsउन के बिना उचित मूल्य वापस नहीं आएगा।


1
दोस्त नई स्विफ्ट से पूछा कि इसे कैसे उपयोग करना है, बस किसी और को नहीं पता है ... if DeviceType.iPhoneX { //do something for iPhone X notch }else{ // don’t do anything about notch }
लियाम बोलिंग

5

सभी उत्तर जो उपयोग कर heightरहे हैं वे एक कारण से कहानी का केवल आधा हिस्सा हैं। यदि आप इस तरह की जांच करने जा रहे हैं कि डिवाइस ओरिएंटेशन कब है landscapeLeftया landscapeRightचेक फेल हो जाएगा, क्योंकि heightइसके साथ स्वैप किया गया हैwidth

यही कारण है कि मेरा समाधान स्विफ्ट 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

आपको यह नहीं मान लेना चाहिए कि केवल डिवाइस जिसे Apple एक अलग UINavigationBar ऊंचाई के साथ जारी करता है, वह iPhone X होगा। अधिक सामान्य समाधान का उपयोग करके इस समस्या को हल करने का प्रयास करें। यदि आप चाहते हैं कि बार हमेशा उसकी डिफ़ॉल्ट ऊंचाई से 20px बड़ा हो, तो आपके कोड को 64px (44px + 20px) सेट करने के बजाय, बार की ऊँचाई में 20px जोड़ना चाहिए।


तो, प्रस्ताव करने के लिए आपके पास और क्या उपाय है?
स्टीफन मैथिस

@xaphod के अब बेहतर जवाब हैं।
Cœur

4
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

स्विफ्ट 3 + 4:

बिना किसी डिवाइस आकार के पिक्सेल मूल्य की आवश्यकता

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

उदाहरण:

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

3
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_X (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0f)

2
यदि आप iPhone X के लिए डिफ़ॉल्ट छवि अपलोड करते हैं, तो यह आपको 812 वापस कर देगा। तब तक मुझे लगता है कि यह आपको iPhone 7 आकार लौटा देगा, हालांकि यह निश्चित नहीं है ...
Fahim Parkar

3
- (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;
    }
}

1
सबसे बढ़िया उत्तर! किसी भी डिवाइस के आकार की आवश्यकता के बिना पिक्सेल मूल्य।
पीटर क्रेन्ज़

3

आमतौर पर, प्रोग्रामर को इसे ऊपर या नीचे करने के लिए विवश करने की आवश्यकता होती है, इसलिए ये तरीके मदद कर सकते हैं

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
}

IPhone X से पहले के लिए ये तरीके वापस आते हैं: 0

IPhone X के लिए: 44 और उसके अनुसार 34

फिर बस इन एक्स्ट्रा को ऊपर या नीचे की बाधाओं में जोड़ें


3

देशी सीमा की ऊँचाई (मेरे जैसे) के लिए 2436px के बजाय 2001px पाने वालों के लिए, यह इसलिए है क्योंकि आपने iOS 11 (Xcode 9 के बजाय Xcode 8) से पहले अपना ऐप पुराने SDK के साथ बनाया था। पुराने एसडीके के साथ, आईओएस एक्स "एक्स-टू-एज" को फैलाने के बजाय आईफोन एक्स पर "ब्लैक बॉक्सिंग" ऐप प्रदर्शित करेगा, शीर्ष "सेंसर नॉच" से परे। इससे स्क्रीन का आकार कम हो जाता है, यही वजह है कि यह संपत्ति 2436 के बजाय 2001 में वापस आ जाती है।

सबसे सरल समाधान दोनों आकारों की जांच करना है यदि आप केवल डिवाइस का पता लगाने में रुचि रखते हैं। मैंने एक पुराने Xcode SDK के साथ निर्माण करते समय FaceID का पता लगाने के लिए इस पद्धति का उपयोग किया, जिसमें बायोमेट्रिक प्रकार निर्दिष्ट करने वाला ENUM मान नहीं है। इस स्थिति में, स्क्रीन की ऊँचाई का उपयोग करने वाले डिवाइस का पता लगाना यह जानने का सबसे अच्छा तरीका था कि डिवाइस में फेसकोड बनाम टचआईडी था या नहीं, जो कि Xcode को अपडेट किए बिना था।


3

स्क्रीन पिक्सेल आकार का उपयोग न करें जैसा कि अन्य समाधानों ने सुझाव दिया है, यह बुरा है क्योंकि इससे भविष्य के उपकरणों के लिए झूठी सकारात्मकता हो सकती है; अगर UIWindow ने अभी तक रेंडर नहीं किया है तो (AppDelegate) काम नहीं करेगा, लैंडस्केप ऐप में काम नहीं करेगा, और अगर स्केल सेट है तो सिम्युलेटर पर विफल हो सकता है।

इसके बजाय, मैंने इस उद्देश्य के लिए एक मैक्रो बनाया है, इसका उपयोग करना बहुत आसान है और उपरोक्त मुद्दों को रोकने के लिए हार्डवेयर झंडे पर निर्भर करता है।

संपादित करें: iPhoneX, iPhone XS, iPhoneXR, iPhoneXS मैक्स को सपोर्ट करने के लिए अपडेट किया गया


उपयोग करने के लिए:

if (IS_DEVICE_IPHONEX) {
    //do stuff
}

हाँ, वास्तव में।


मैक्रो:

बस इसे कहीं भी कॉपी पेस्ट करें, मैं अपने .h फ़ाइल के बहुत नीचे पसंद करता हूं @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]);\
})()\
)

IPhoneX का पता लगाने का एकमात्र कारण मैं स्क्रीन के शीर्ष पर पायदान से बचना है; यदि ऐसा है तो आप कहावत के आकार का पता लगाने के लिए safeArea.top की जांच कर सकते हैं। बस सुनिश्चित करें कि आप UIWindow लोड होने के बाद इसे मापते हैं, इसलिए व्यूडीडलड के दौरान नहीं बल्कि एक थ्रेड-साइकिल के बाद:if (@available(iOS 11.0, *)) { [UIApplication sharedApplication].keyWindow.safeAreaInsets.top }
अल्बर्ट रेनशॉ

2

मैंने आपके अन्य उत्तरों के बारे में विस्तार से बताया और UIDevice पर तेजी से विस्तार किया। मुझे स्विफ्ट एनम और "ऑर्डर में सब कुछ" और परमाणु पसंद है। मैंने समाधान बनाया है जो डिवाइस और सिम्युलेटर दोनों पर काम करता है।

लाभ: - सरल इंटरफ़ेस, उपयोग जैसे UIDevice.current.isIPhoneX - UIDeviceModelTypeएनम आपको आसानी से मॉडल विशिष्ट सुविधाओं और स्थिरांक का विस्तार करने की क्षमता देता है जिसे आप अपने ऐप में उपयोग करना चाहते हैं, जैसे कोनेरेडियस

नुकसान: - यह मॉडल विशिष्ट समाधान है, संकल्प विशिष्ट नहीं - उदाहरण के लिए यदि Apple उसी स्पेक्स के साथ एक और मॉडल का उत्पादन करेगा, तो यह सही ढंग से काम नहीं करेगा और आपको यह कार्य करने के लिए एक और मॉडल जोड़ने की आवश्यकता है => आपको अपना अपडेट करने की आवश्यकता है एप्लिकेशन।

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

उपयोग करने के बजाय Mirror, यह sysctlbynameCloud9999Strife उत्तर (और मेरे उत्तर में भी) में उपयोग करने के लिए तेज़ होगा ।
œ --œœ

2

अगर यह iPhone X है, तो मैं यह पता लगाने के लिए स्टेटस बार फ्रेम ऊँचाई पर भरोसा करता हूँ:

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

यह एप्लीकेशन अन पोर्ट्रेट के लिए है। आप डिवाइस के उन्मुखीकरण के अनुसार आकार की जांच भी कर सकते हैं। इसके अलावा, अन्य iPhones पर, Status Bar छिपाया जा सकता है, इसलिए फ्रेम की ऊँचाई है 0। IPhone X पर, स्टेटस बार कभी नहीं छिपा होता है।


आप इसमें iPhoneX स्टेटस छिपा सकते हैं controller: - (BOOL)prefersStatusBarHidden { return YES; } तब स्टेटसबार की ऊंचाई 0. है

@ @ Boot 之 星辰 मैं इसे AppDelegate में बूट समय पर जाँचता हूँ।
टायो

2

मैं पीटर क्रिन्ज़ के कोड का उपयोग कर रहा था (क्योंकि यह साफ था और मुझे जो चाहिए था) किया गया था, लेकिन तब मुझे एहसास हुआ कि यह तब काम करता है जब डिवाइस पोर्ट्रेट पर हो (चूंकि शीर्ष पैडिंग शीर्ष पर होगी, जाहिर है) इसलिए मैंने सभी को संभालने के लिए एक एक्सटेंशन बनाया स्क्रीन आकार पर रिले किए बिना, इसके संबंधित पैडिंग के साथ झुकाव:

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

और आपकी कॉल साइट पर आप बस:

let res = UIDevice.current.isIphoneX

2

वैकल्पिक रूप से, आप ' DeviceKit ' पॉड की जांच कर सकते हैं । एक बार स्थापित होने के बाद, आपको डिवाइस की जांच करने के लिए सभी आवश्यक है:

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

2

नवंबर 2019:

यहां मैं अपनी सभी उत्पादन परियोजनाओं में उपयोग करता हूं। ध्यान दें कि यह पकड़ काफी लंबी है।

  1. यह चौड़ाई या ऊंचाई की गणना का उपयोग नहीं करता है, बल्कि:
  2. यह डिवाइस स्ट्रिंग मॉडल की जांच करता है।
  3. किसी भी निजी / अनिर्दिष्ट एपीआई का उपयोग करने के कारण Apple द्वारा आपके निर्माण को अस्वीकार करने का जोखिम नहीं है।
  4. सिमुलेटर 💯 के साथ काम करता है

    import UIKit
    
    class DeviceUtility {
        /// Determines if the current device of the user is an iPhoneX type/variant.
        static var isIphoneXType: Bool {
            get {
                switch UIDevice().type {
                case .iPhoneXR, .iPhoneXS, .iPhoneXSMax, .iPhoneX, .iPhone11, .iPhone11Pro, .iPhone11ProMax: return true
                default: return false
                }
            }
        }
    }
    
    
    public enum DeviceModel : String {
        case simulator     = "simulator/sandbox",
    
        // MARK: - iPods
    
        iPod1              = "iPod 1",
        iPod2              = "iPod 2",
        iPod3              = "iPod 3",
        iPod4              = "iPod 4",
        iPod5              = "iPod 5",
    
        // MARK: - iPads
    
        iPad2              = "iPad 2",
        iPad3              = "iPad 3",
        iPad4              = "iPad 4",
        iPadAir            = "iPad Air ",
        iPadAir2           = "iPad Air 2",
        iPad5              = "iPad 5", //aka iPad 2017
        iPad6              = "iPad 6", //aka iPad 2018
    
        // MARK: - iPad Minis
    
        iPadMini           = "iPad Mini",
        iPadMini2          = "iPad Mini 2",
        iPadMini3          = "iPad Mini 3",
        iPadMini4          = "iPad Mini 4",
    
        // MARK: - iPad Pros
    
        iPadPro9_7         = "iPad Pro 9.7\"",
        iPadPro10_5        = "iPad Pro 10.5\"",
        iPadPro12_9        = "iPad Pro 12.9\"",
        iPadPro2_12_9      = "iPad Pro 2 12.9\"",
    
        // MARK: - iPhones
    
        iPhone4            = "iPhone 4",
        iPhone4S           = "iPhone 4S",
        iPhone5            = "iPhone 5",
        iPhone5S           = "iPhone 5S",
        iPhone5C           = "iPhone 5C",
        iPhone6            = "iPhone 6",
        iPhone6plus        = "iPhone 6 Plus",
        iPhone6S           = "iPhone 6S",
        iPhone6Splus       = "iPhone 6S Plus",
        iPhoneSE           = "iPhone SE",
        iPhone7            = "iPhone 7",
        iPhone7plus        = "iPhone 7 Plus",
        iPhone8            = "iPhone 8",
        iPhone8plus        = "iPhone 8 Plus",
        iPhoneX            = "iPhone X",
        iPhoneXS           = "iPhone XS",
        iPhoneXSMax        = "iPhone XS Max",
        iPhoneXR           = "iPhone XR",
        iPhone11           = "iPhone 11",
        iPhone11Pro        = "iPhone 11 Pro",
        iPhone11ProMax     = "iPhone 11 Pro Max",
    
        // MARK: - Apple TVs
    
        AppleTV            = "Apple TV",
        AppleTV_4K         = "Apple TV 4K",
    
        // MARK: - Unrecognized
    
        unrecognized       = "?unrecognized?"
    }
    
    // #-#-#-#-#-#-#-#-#-#-#-#-#-#-#
    //MARK: UIDevice extensions
    // #-#-#-#-#-#-#-#-#-#-#-#-#-#-#
    
    public extension UIDevice {
        var type: DeviceModel {
            var systemInfo = utsname()
            uname(&systemInfo)
            let modelCode = withUnsafePointer(to: &systemInfo.machine) {
                $0.withMemoryRebound(to: CChar.self, capacity: 1) {
                    ptr in String.init(validatingUTF8: ptr)
    
                }
            }
            let modelMap : [ String : DeviceModel ] = [
    
                // MARK: - Simulators
    
                "i386"      : .simulator,
                "x86_64"    : .simulator,
    
                // MARK: - iPod
    
                "iPod1,1"   : .iPod1,
                "iPod2,1"   : .iPod2,
                "iPod3,1"   : .iPod3,
                "iPod4,1"   : .iPod4,
                "iPod5,1"   : .iPod5,
    
                // MARK: - iPad
    
                "iPad2,1"   : .iPad2,
                "iPad2,2"   : .iPad2,
                "iPad2,3"   : .iPad2,
                "iPad2,4"   : .iPad2,
                "iPad3,1"   : .iPad3,
                "iPad3,2"   : .iPad3,
                "iPad3,3"   : .iPad3,
                "iPad3,4"   : .iPad4,
                "iPad3,5"   : .iPad4,
                "iPad3,6"   : .iPad4,
                "iPad4,1"   : .iPadAir,
                "iPad4,2"   : .iPadAir,
                "iPad4,3"   : .iPadAir,
                "iPad5,3"   : .iPadAir2,
                "iPad5,4"   : .iPadAir2,
                "iPad6,11"  : .iPad5, //aka iPad 2017
                "iPad6,12"  : .iPad5,
                "iPad7,5"   : .iPad6, //aka iPad 2018
                "iPad7,6"   : .iPad6,
    
                // MARK: - iPad mini
    
                "iPad2,5"   : .iPadMini,
                "iPad2,6"   : .iPadMini,
                "iPad2,7"   : .iPadMini,
                "iPad4,4"   : .iPadMini2,
                "iPad4,5"   : .iPadMini2,
                "iPad4,6"   : .iPadMini2,
                "iPad4,7"   : .iPadMini3,
                "iPad4,8"   : .iPadMini3,
                "iPad4,9"   : .iPadMini3,
                "iPad5,1"   : .iPadMini4,
                "iPad5,2"   : .iPadMini4,
    
                // MARK: - iPad pro
    
                "iPad6,3"   : .iPadPro9_7,
                "iPad6,4"   : .iPadPro9_7,
                "iPad7,3"   : .iPadPro10_5,
                "iPad7,4"   : .iPadPro10_5,
                "iPad6,7"   : .iPadPro12_9,
                "iPad6,8"   : .iPadPro12_9,
                "iPad7,1"   : .iPadPro2_12_9,
                "iPad7,2"   : .iPadPro2_12_9,
    
                // MARK: - iPhone
    
                "iPhone3,1" : .iPhone4,
                "iPhone3,2" : .iPhone4,
                "iPhone3,3" : .iPhone4,
                "iPhone4,1" : .iPhone4S,
                "iPhone5,1" : .iPhone5,
                "iPhone5,2" : .iPhone5,
                "iPhone5,3" : .iPhone5C,
                "iPhone5,4" : .iPhone5C,
                "iPhone6,1" : .iPhone5S,
                "iPhone6,2" : .iPhone5S,
                "iPhone7,1" : .iPhone6plus,
                "iPhone7,2" : .iPhone6,
                "iPhone8,1" : .iPhone6S,
                "iPhone8,2" : .iPhone6Splus,
                "iPhone8,4" : .iPhoneSE,
                "iPhone9,1" : .iPhone7,
                "iPhone9,3" : .iPhone7,
                "iPhone9,2" : .iPhone7plus,
                "iPhone9,4" : .iPhone7plus,
                "iPhone10,1" : .iPhone8,
                "iPhone10,4" : .iPhone8,
                "iPhone10,2" : .iPhone8plus,
                "iPhone10,5" : .iPhone8plus,
                "iPhone10,3" : .iPhoneX,
                "iPhone10,6" : .iPhoneX,
                "iPhone11,2" : .iPhoneXS,
                "iPhone11,4" : .iPhoneXSMax,
                "iPhone11,6" : .iPhoneXSMax,
                "iPhone11,8" : .iPhoneXR,
                "iPhone12,1" : .iPhone11,
                "iPhone12,3" : .iPhone11Pro,
                "iPhone12,5" : .iPhone11ProMax,
    
                // MARK: - AppleTV
    
                "AppleTV5,3" : .AppleTV,
                "AppleTV6,2" : .AppleTV_4K
            ]
    
            if let model = modelMap[String.init(validatingUTF8: modelCode!)!] {
                if model == .simulator {
                    if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
                        if let simModel = modelMap[String.init(validatingUTF8: simModelCode)!] {
                            return simModel
                        }
                    }
                }
                return model
            }
            return DeviceModel.unrecognized
        }
    }

उपयोग: इनसेट दें: CGFloat = DeviceUtility.isIphoneXType? 50.0: 40.0


अच्छी तरह से काम। धन्यवाद। मैं इसे एक SwiftUI प्रोजेक्ट में उपयोग कर रहा हूं।
लंदनगुए

1

मुझे हाल ही में इसी मुद्दे को हल करना था। और जब इस सवाल का निश्चित रूप से जवाब दिया जाता है ("नहीं"), इससे उन लोगों को मदद मिल सकती है जिन्हें iPhone X के विशिष्ट लेआउट व्यवहार की आवश्यकता है।

मुझे वास्तव में इस बात में कोई दिलचस्पी नहीं थी कि क्या डिवाइस iPhone X था। मुझे इस बात में दिलचस्पी थी कि क्या डिवाइस में एक नोकदार डिस्प्ले था।

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
}

आप hasOnScreenHomeIndicatorउसी तर्ज पर एक चर भी लिख सकते हैं (हालाँकि नीचे सुरक्षित क्षेत्र की जाँच करें, हो सकता है?)।

उपरोक्त UIViewआईओएस 10 और उससे पहले के सुरक्षित क्षेत्र के इनसेट के लिए सुविधाजनक पहुंच के लिए मेरे एक्सटेंशन का उपयोग करता है ।

@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

में पोर्ट्रेट केवल मैं जाँच करने के लिए देखने के फ्रेम के चौड़ाई और ऊंचाई का उपयोग करें:

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

}

पोर्ट्रेट स्क्रीन आयाम यहां सूचीबद्ध हैं

यहां छवि विवरण दर्ज करें


0

यह जानने के लिए कई कारण हैं कि डिवाइस क्या है।

  1. आप डिवाइस की ऊंचाई (और चौड़ाई) की जांच कर सकते हैं। यह लेआउट के लिए उपयोगी है, लेकिन आप आमतौर पर ऐसा नहीं करना चाहते हैं यदि आप सटीक डिवाइस जानना चाहते हैं।

  2. लेआउट उद्देश्यों के लिए, आप भी उपयोग कर सकते हैं UIView.safeAreaInsets

  3. यदि आप उपकरण का नाम प्रदर्शित करना चाहते हैं, उदाहरण के लिए, नैदानिक ​​प्रयोजनों के लिए एक ईमेल में शामिल किया जाना है sysctl (), तो उपयोग करने वाले डिवाइस मॉडल को पुनर्प्राप्त करने के बाद , आप नाम का पता लगाने के लिए इसके बराबर का उपयोग कर सकते हैं:

    $ curl http://appledevicenames.com/devices/iPhone10,6
    
    iPhone X
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.