रेटिना डिस्प्ले का पता लगाएं


223

क्या iOS SDK यह जांचने का एक आसान तरीका प्रदान करता है कि क्या currentDevice में उच्च-रिज़ॉल्यूशन डिस्प्ले (रेटिना) है?

सबसे अच्छा तरीका है जो मैंने अभी किया है:

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00) {
         // RETINA DISPLAY
    }

जिज्ञासा से बाहर - जब आप अपनी कला के काम के बड़े संस्करण दिखाने के अलावा प्रदर्शन का पता लगाते हैं तो आप क्या कर रहे हैं?
माइकल बेहान

4

@ मबेहन: मेरे पास एक TTImageView (तीन20 की रूपरेखा देखें) है और मैं छवि का एक उच्च-रिज़ॉल्यूशन यूआरएल देना चाहता हूं।
पियरे वालेड

1
यह प्रश्न मेरे लिए भी उपयोगी है क्योंकि मैंने उन छवियों को डाउनलोड किया है जो यूआई के रूप में सभी 4 डिस्प्ले आकारों में उपलब्ध हैं और केवल उपयोगकर्ताओं को उपयुक्त डाउनलोड करना चाहते हैं।
पेड्रो

@ मबेहन: मेरे मामले में मुझे कस्टम सेल विभाजक चाहिए थे जो रेटिना और गैर-रेटिना स्क्रीन (देशी विभाजकों की तरह) पर 1px हैं। रेटिना डिस्प्ले (स्पष्ट रूप से) पर 2px पर 1px रेंडरर्स की मोटाई सेट करना।
user3099609

जवाबों:


295

सभी iOS उपकरणों पर विश्वसनीय रूप से रेटिना डिस्प्ले का पता लगाने के लिए, आपको यह जांचने की आवश्यकता है कि क्या डिवाइस iOS4 + चल रहा है और यदि [UIScreen mainScreen].scaleसंपत्ति 2.0 के बराबर है। आप मान सकते हैं कि कोई उपकरण iOS4 + चला रहा है यदि scaleसंपत्ति मौजूद है, क्योंकि iPad 3.2 में भी यह संपत्ति है।

IOS3.2 पर चलने वाले iPad पर, स्केल 1x मोड में 1.0 और 2x मोड में 2.0 वापस आ जाएगा - भले ही हम जानते हैं कि डिवाइस में रेटिना डिस्प्ले नहीं है। Apple ने iPad के लिए iOS4.2 में इस व्यवहार को बदल दिया: यह 1x और 2x दोनों मोड में 1.0 देता है। आप इसे सिम्युलेटर में खुद का परीक्षण कर सकते हैं।

मैं -displayLinkWithTarget:selector:उस मुख्य स्क्रीन पर विधि के लिए परीक्षण करता हूं जो iOS4.x में मौजूद है लेकिन iOS3.2 में नहीं है, और फिर स्क्रीन के पैमाने की जांच करें:

if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] &&
    ([UIScreen mainScreen].scale == 2.0)) {
  // Retina display
} else {
  // non-Retina display
}

आप कहते हैं कि "Apple ने iOS के लिए iOS4.2 में इस व्यवहार को बदल दिया है", जिसका अर्थ है कि iOS4.1 में, आपका कोड ऊपर वापस आ जाएगा "2x में एक iPhone ऐप चलाने वाले iPad के लिए" रेटिना है "। क्या मै गलत हु?
मकदाद

9
IPad के लिए 4.1 कभी नहीं था। केवल 3.2, फिर 4.2।
जॉनी

11
यह कॉल थोड़ा महंगा है, इसलिए मैं इसे शुरू करने और ऐप में उपयोग करने के साथ BOOL को इनिशियलाइज़ करूँगा।
n13

मैं संस्करण का उपयोग करके जांच करना पसंद करता हूं [UIDevice currentDevice].systemVersion]। इस मामले में यह होगा NSString *currentSystemVersion = [[UIDevice currentDevice] systemVersion]; return [currentSystemVersion compare:version options:NSNumericSearch];
सैंडी चैपमैन

Xcode 4 में गैर रेटिना iPad (ios 7.1) के लिए सिम्युलेटर में काम करना प्रतीत नहीं होता है ... अजीब।
इसहाक पॉल

81

@ सिपाही का जवाब सही है। बस चीजों को आसान बनाने के लिए, इस लाइन को अपनी Shared.pch फ़ाइल में जोड़ें:

#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale >= 2.0))

फिर किसी भी फ़ाइल में आप कर सकते हैं:

if(IS_RETINA)
{
   // etc..
}

यह सिम्युलेटर पर काम नहीं करता है। क्या यह उत्तरदाता के कारण है? सिम्युलेटर चयनकर्ता का जवाब नहीं देता है?
अर्नियोटकी

2
महान! हालाँकि यदि आप iPhone 6 प्लस को ध्यान में रखना चाहते हैं तो आपको स्केल> = 2.0 के लिए जाँच करनी चाहिए।
इवान कैरोसाटी

20
+(BOOL)iPhoneRetina{
    return ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))?1:0;
}

23
क्यों ?1:0? क्या यह नहीं दोहराया गया है कि अभिव्यक्ति के बूलियन भाग में पहले से ही क्या गणना की गई है?
d11wtq

9

यहाँ एक आसान स्विफ्ट एक्सटेंशन है:

स्विफ्ट v5 के लिए अपडेट:

extension UIScreen {

    public var isRetina: Bool {
        guard let scale = screenScale else {
            return false
        }
        return scale >= 2.0
    }

    public var isRetinaHD: Bool {
        guard let scale = screenScale else {
            return false
        }
        return scale >= 3.0
    }

    private var screenScale: CGFloat? {
        guard UIScreen.main.responds(to: #selector(getter: scale)) else {
            return nil
        }
        return UIScreen.main.scale
    }
}

उपयोग:

if UIScreen.main.isRetina {
    // Your code
}

मूल:

extension UIScreen { 
public func isRetina() -> Bool {
    return screenScale() >= 2.0
}

public func isRetinaHD() -> Bool {
    return screenScale() >= 3.0
}

private func screenScale() -> CGFloat? {
    if UIScreen.mainScreen().respondsToSelector(Selector("scale")) {
        return UIScreen.mainScreen().scale
    }
    return nil
    }
}

उपयोग:

if UIScreen.mainScreen().isRetina() {
 // your code
        }

यदि Swift 5 isRetinaHD जाँच के लिए काम करने के लिए अपडेट किया गया कोड नहीं होना चाहिए, तो iscreenScale है> = 3.0 2.0 नहीं ??? संपादित करें: मैंने इसे अपडेट किया ...
C0D3

6

यह स्निपेट ...

    int d = 0; // standard display
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0) {
    d = 1; // is retina display
}

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    d += 2;
}

वापस आ जाएगा ... मानक संकल्प iPhone / iPod टच के लिए 0, रेटिना iPhone के लिए 1, मानक संकल्प iPad के लिए 2, रेटिना iPad के लिए 3।


6

SSToolkit में एक विधि है जो ऐसा करती है:

http://sstoolk.it/documentation/Categories/UIScreen(SSToolkitAdditions).html

इसका उपयोग निम्नलिखित तरीके से किया जाता है:

[[UIScreen mainScreen] isRetinaDisplay];

SSToolKit के भीतर SAMCategories द्वारा इस विशेष उपयोग को हटा दिया गया है: [[UIScreen mainScreen] sam_isRetina]
बजे

5

समानता के लिए फ्लोटिंग-पॉइंट मूल्यों की तुलना करने के लिए यह हमेशा थोड़ा अजीब लगता है। मैं या तो जाना पसंद करता हूं

[UIScreen mainScreen].scale > 1.0;

या

[UIScreen mainScreen].scale < 2.0;

5
समानता के लिए दो फ़्लोटिंग-पॉइंट मूल्यों की तुलना "डोडी महसूस करता है", क्योंकि गणना के बाद वे अभिन्न मूल्यों से थोड़ा भिन्न हो सकते हैं। लेकिन <या> के साथ तुलना करना उन स्थितियों में सिर्फ डोडी जैसा है। इस मामले में, हालांकि, इस बात का कोई मौका नहीं है कि यह स्केल 1.0 या 2.0 नहीं है, क्योंकि यह हार्डवेयर परिभाषित है।
मछली मारना

जैसा कि @fishinear बताता है, जैसे कुछ का उपयोग करने के लिए बेहतर है isRetina = [UIScreen mainScreen].scale > 1.95। यह @ 4x के साथ आने पर भी लचीला होने का फ़ायदा होगा :)
डेनियल आयटेकिन

मैं दृढ़ता से असहमत हूँ। जरूरत न होने पर ऐसा करना कोड को कम पठनीय बनाता है। भविष्य के प्रमाण पर बिंदु की वैधता हो सकती है, लेकिन मुझे संदेह है कि हमारे पास @ 4x स्क्रीन जल्द ही (यदि बिल्कुल भी) हो।
रिकार्डो सांचेज-सेज

गलत। सिर्फ इसलिए कि यह "हार्डवेयर परिभाषित" है, किसी भी तरह से, मतलब नहीं है कि आप तुलना-ए-फ्लोट समस्या से बचें। (यह किसी भी अन्य की तरह एक फ्लोट है।) किसी भी फ्लोट के साथ, सामान्य रूप से आप कभी भी == का उपयोग नहीं कर सकते, आपको एक> या <तुलना का उपयोग करना चाहिए। निश्चितता के बारे में> 1.5 क्या है।
फेटी

2

यह ऊपर मैट एमसी के जवाब पर एक दरार है। बस एक श्रेणी पर UIScreen

#import "UIScreen+Util.h"

@implementation UIScreen (Util)

+ (BOOL) isRetinaDisplay {
    static BOOL retina = NO;
    static BOOL alreadyChecked = NO;
    if (!alreadyChecked) {
        UIScreen *mainScreen = self.mainScreen;
        if (mainScreen) {
            retina = mainScreen.scale > 1.0;
            alreadyChecked = YES;
        }
    }
    return retina;
}

@end

1
मुझे संदेह है कि कैशिंग का alreadyCheckedआभार है, लेकिन यह ठीक है।
डेन रोसेनस्टार्क

@NikolayShubenkov यही कारण है कि मैंने पहले से ही अंतिम सेट किया है। सबसे खराब स्थिति में, आप अतिरिक्त समय या दो की जांच करने के लिए कोड चलाते हैं।
डैन रोसेनस्टार्क

मेरा मतलब है कि जब एक प्रक्रिया पहले से ही जांचने की कोशिश करेगी जबकि अन्य वर्तमान में इस मूल्य एप को पढ़ रहा है तो दुर्घटना हो सकती है। मैं उस पंक्ति को जोड़ूंगा: @synchronyze (पहले से चेक किया हुआ) {पहले से ही भेजा गया = YES}
निकोले शुबेनकोव

2

उपरोक्त उत्तरों का स्विफ्ट संस्करण,> = 2.0 स्केल के साथ इसलिए इसमें iPhone 6+ और उच्च-रेटिना स्केल वाले अन्य भविष्य के डिवाइस शामिल हैं:

 if UIScreen.mainScreen().respondsToSelector(Selector("scale")) && UIScreen.mainScreen().scale >= 2.0 {
    // code executed only on Retina device
}

1

बस @sickp से उत्तर को संयोजित करने के लिए और @ n13 से निम्न टिप्पणी को मैंने इसे UIScreen श्रेणी में शामिल किया, जो अच्छी तरह से काम करता है। चेक को पहली बार किया जाता है जब आप इसे कॉल करते हैं और फिर बाद में कॉल के लिए सहेजा जाता है।

@interface UIScreen (RetinaCheck)
+ (BOOL)retinaScreen;
@end

static BOOL isRetinaScreen = NO;
static BOOL didRetinaCheck = NO;

@implementation UIScreen (RetinaCheck)
+ (BOOL)retinaScreen
{
    if (!didRetinaCheck) {
        isRetinaScreen = ([[self mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] &&
                          ([self mainScreen].scale == 2.0));
        didRetinaCheck = YES;
    }
    return isRetinaScreen;
}
@end

किसी के लिए उपयोगी हो सकता है।


कैशिंग कोड के लिए धन्यवाद। मेरा एकमात्र सुझाव है कि इसे बनाने के (Util)बजाय (RetinaCheck)... शायद यह कम स्पष्ट है, लेकिन यह अन्य उपयोगों के लिए उधार देता है। इसके अलावा, मैं उस विधि isRetinaDisplayया किसी चीज़ का नाम रखूँगा जो इसके साथ शुरू होती है is, लेकिन शायद मैं ओब्ज-सी के दिशानिर्देशों को कभी नहीं समझता था। इसके अलावा, मैं एक प्रशंसक हूं > 1.0लेकिन जो जानता है कि आगे बढ़ने से क्या होगा।
दान रोसेनस्टार्क

1
// .h
UIKIT_EXTERN bool isRetinaDisplay();

// .m
bool isRetinaDisplay()
{
    static bool flag;
#ifdef __BLOCKS__
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
        {
            flag = [[UIScreen mainScreen] scale] > 1.0;
        }
        else
        {
            flag = false;
        }
    });
#else
    static bool onceToken;
    if(onceToken == false)
    {
        onceToken = true;
        if([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
        {
            flag = [[UIScreen mainScreen] scale] > 1.0;
        }
        else
        {
            flag = false;
        }
    }
#endif
    return flag;
}

सबसे अच्छा समाधान जैसा कि मुझे लगता है।
निकोले शुबेनकोव

0

इसे इस्तेमाल करे

if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] &&
    ([UIScreen mainScreen].scale == 2.0))
{
    // Retina display
    NSLog(@"---------------Retina display");
} else {
    // non-Retina display
    NSLog(@"---------------non-Retina display");
}

0

सबसे आम उपयोग के मामलों की सरलता के लिए प्रिमुलाविसिस का संशोधित संस्करण। मैं तेजी से 2.2 पर हूँ, लेकिन यह बात नहीं होनी चाहिए।

extension UIScreen {
    static var isRetina: Bool {
        return screenScale >= 2.0
    }

    static var isRetinaHD: Bool {
        return screenScale >= 3.0
    }

    static var screenScale:CGFloat {
        return UIScreen.mainScreen().scale
    }
}

तो बस उन्हें इस तरह का उपयोग करें

print(UIScreen.isRetina)
print(UIScreen.isRetinaHD)
print(UIScreen.screenScale)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.