क्या [UIScreen mainScreen] .bounds.size iOS8 में अभिविन्यास-निर्भर बन रहा है?


184

मैंने iOS 7 और iOS 8 दोनों में निम्न कोड चलाया:

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL landscape = (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight);
NSLog(@"Currently landscape: %@, width: %.2f, height: %.2f", 
      (landscape ? @"Yes" : @"No"), 
      [[UIScreen mainScreen] bounds].size.width, 
      [[UIScreen mainScreen] bounds].size.height);

निम्नलिखित iOS 8 से परिणाम है:

Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 568.00, height: 320.00

IOS 7 में परिणाम की तुलना:

Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 320.00, height: 568.00

क्या कोई दस्तावेज़ इस बदलाव को निर्दिष्ट कर रहा है? या यह iOS 8 एपीआई में एक अस्थायी बग है?


13
अच्छी तरह से iOS8 आउटपुट ज्यादा तार्किक लगता है
Levi

जवाबों:


173

हां, यह iOS8 में ओरिएंटेशन-डिपेंडेंट है, बग नहीं। आप अधिक जानकारी के लिए WWDC 2014 से सत्र 214 की समीक्षा कर सकते हैं: "iOS 8 में कंट्रोलर एडवांसमेंट देखें"

प्रस्तुति से उद्धरण:

UIScreen अब इंटरफ़ेस उन्मुख है:

  • [UIScreen सीमा] अब इंटरफ़ेस उन्मुख है
  • [UIScreen आवेदनफ्रेम] अब इंटरफ़ेस उन्मुख है
  • स्टेटस बार फ्रेम नोटिफिकेशन इंटरफेस-ओरिएंटेड हैं
  • कीबोर्ड फ़्रेम सूचनाएं इंटरफ़ेस-उन्मुख हैं

7
ऊपर वर्णित WWDC व्याख्यान में, इंटरफ़ेस उन्मुख भाग 51:50 से शुरू होता है।
cnotethegr8 10

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

1
@ बरोबर आप कुछ पुराने आवासों को तोड़ने के बिना नया नहीं कर सकते।
बोरिस वाई।

23
@ शोर - मैं सम्मान से असहमत हूँ। ज्यादातर मामलों में यह संभव है कि पीछे की अनुकूलता को संरक्षित करते हुए नया किया जाए। मेरी राय में, किसी भी चीज़ से ज्यादा आलस की बदबू से ब्रेकअप बदल जाता है। वे चाहते हैं कि बाकी सब लोग काम करें।
एरोथ

1
यह उत्तर और भी अधिक उपयोगी होगा यदि यह समझाया गया कि इंटरफ़ेस उन्मुख वास्तव में क्या मतलब है। मैं गलत हो सकता हूं, लेकिन मुझे लगता है कि अभिविन्यास निर्भरता केवल नियंत्रकों को देखने से संबंधित है। यदि आप किसी अन्य वर्ग को लेते हैं और सीमा की गणना करते हैं, तो वे अभी भी पुरानी शैली के अनुसार हैं, हमेशा चित्र।
मैक्सी मुस

59

हां, यह iOS8 में ओरिएंटेशन-डिपेंडेंट है।

मैंने उन ऐप्स के लिए इस समस्या को हल करने के लिए एक यूटिल विधि लिखी, जिन्हें ओएस के पुराने संस्करणों का समर्थन करने की आवश्यकता है।

+ (CGSize)screenSize {
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        return CGSizeMake(screenSize.height, screenSize.width);
    }
    return screenSize;
}

1
मैंने कोड की जांच की, कृपया ओएस संस्करण की जांच के लिए आपकी स्थिति गलत थी
जैजेन

@ जैजेन कृपया स्पष्ट करें, संस्करण जांच मेरे लिए काम करती है। समस्या क्या है?
22

अगर मैं समझता हूं कि हमें ऊंचाई और चौड़ाई को बदलना होगा अगर ओएस iOS8 है और ओरिएंटेशन लैंडस्केप है, क्या मैं सही हूं?
जगेन

@Jageen नकारात्मक, iOS 8 में विधि अभिविन्यास-निर्भर है। आपका तर्क बदल गया है। आपका संपादन सही ढंग से अस्वीकार कर दिया गया था।
21

@cartel इसे UIScreen में वर्गीकृत करने का एक तरीका है ताकि हमारी मूल कॉल [UIScreenScreen] पर हो ।bounds.size iOS 7 और iOS 8 दोनों के लिए काम करेगा?
केविनल

34

हां, वास्तव में, स्क्रीन का आकार अब iOS 8 में उन्मुखीकरण पर निर्भर है। कभी-कभी, हालांकि, यह पोर्ट्रेट ओरिएंटेशन के लिए निश्चित आकार प्राप्त करने के लिए वांछित है। यहाँ है कि मैं यह कैसे करते हैं।

+ (CGRect)screenBoundsFixedToPortraitOrientation {
    UIScreen *screen = [UIScreen mainScreen];

    if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
                    return [screen.coordinateSpace convertRect:screen.bounds toCoordinateSpace:screen.fixedCoordinateSpace];
    } 
    return screen.bounds;
}

2
मुझे लग रहा है कि यह नियमित iPhone ऐप्स के साथ समस्या को ठीक करता है, लेकिन iPad पर चलने वाले iPhone ऐप के साथ नहीं।
थॉमसडब्ल्यू

32

हां, अब यह अभिविन्यास पर निर्भर है।

मैं ऊपर दिए गए कुछ उत्तर दोनों के लिए एक अभिविन्यास-स्वतंत्र तरीके से स्क्रीन आकार प्राप्त करने की निम्न विधि को पसंद करता हूं, क्योंकि यह सरल है और क्योंकि यह किसी भी अभिविन्यास कोड पर निर्भर नहीं करता है (जिसकी स्थिति इस पर निर्भर हो सकती है समय कि वे कहा जाता है) या संस्करण की जाँच पर। आप नया iOS 8 व्यवहार चाहते हैं, लेकिन यह तब काम करेगा जब आपको iOS के सभी संस्करणों पर स्थिर रहने की आवश्यकता होगी।

+(CGSize)screenSizeOrientationIndependent {
     CGSize screenSize = [UIScreen mainScreen].bounds.size;
     return CGSizeMake(MIN(screenSize.width, screenSize.height), MAX(screenSize.width, screenSize.height));
}

संभवतः Apple TV जैसी किसी चीज़ पर काम नहीं होगा, जहाँ यह हमेशा (लगभग) जितना लंबा होता है, उससे कहीं अधिक चौड़ा होता है।
cbh2000

11

इस सवाल से संबंधित है क्योंकि इसने मेरी समस्या को हल किया, यहाँ दो परिभाषित मैं स्क्रीन की चौड़ाई और ऊंचाई की गणना के लिए उपयोग करता हूं:

#define SCREEN_WIDTH (IOS_VERSION_LOWER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) : [[UIScreen mainScreen] bounds].size.width)

#define SCREEN_HEIGHT (IOS_VERSION_LOWER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) : [[UIScreen mainScreen] bounds].size.height)

#define IOS_VERSION_LOWER_THAN_8 (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)

यदि आप iOS 7 और iOS 8 दोनों का समर्थन कर रहे हैं, तो यह इस समस्या का सबसे अच्छा समाधान है।


@ नाम गुप्ता, आपका संपादन गलत है। यदि IOS संस्करण 8 या उससे ऊपर है, तो हम UIScreen आयामों का उपयोग कर सकते हैं क्योंकि ये अभिविन्यास पर निर्भर हैं। IOS 8 से पहले आपको स्टेटसबार ओरिएंटेशन के लिए जांचना था। आपका संपादन अब कह रहा है कि सभी iOS संस्करण कम नहीं हैं तो 8 को स्टेटसबोरिएशन की जांच करनी चाहिए, जो गलत है।
एंटोनी

9

आप nativeBounds(अभिविन्यास-स्वतंत्र) का उपयोग कर सकते हैं

nativeBounds

पिक्सेल में मापी गई भौतिक स्क्रीन की बाउंडिंग आयत। (सिफ़ पढ़िये)

घोषणा स्विफ्ट

  var nativeBounds: CGRect { get }

यह आयत चित्र-अप अभिविन्यास में डिवाइस पर आधारित है। उपकरण के घूमने पर यह मान नहीं बदलता है।

डिवाइस की ऊंचाई का पता लगाना:

if UIScreen.mainScreen().nativeBounds.height == 960.0 {

}

डिवाइस की चौड़ाई का पता लगाना:

if UIScreen.mainScreen().nativeBounds.width == 640.0 {

}

3
विदित हो कि यह विधि पिक्सेल लौटाती है, जबकि अधिकांश अन्य विधियाँ अंकों के साथ व्यवहार करती हैं। बहुत अलग चीजें।
jcsahnwaldt

1
मेरे मामले में वास्तव में मुझे क्या चाहिए :) (OpenGL या अन्य दृश्य UIViews पर आधारित नहीं हैं, लेकिन जहाँ मुझे सटीक पिक्सेल आयाम जानने की आवश्यकता है)
Bersaelor

3
चेतावनी: iphone 6+ पर यह 1080 x 1920 लौटा है जो वह नहीं हो सकता जो आप चाहते हैं
Chanon

8

यह iOS 8 SDK में बग नहीं है। उन्होंने सीमा इंटरफ़ेस अभिविन्यास को निर्भर बनाया। उस तथ्य के बारे में कुछ संदर्भ या प्रलेखन के बारे में आपके प्रश्न के अनुसार, मैं View Controller Advancements in iOS 8इसे देखने के लिए अत्यधिक अनुशंसा करूंगा कि यह WWDC 2014 से 214 सत्र है । सबसे दिलचस्प हिस्सा (आपके संदेह के अनुसार) Screen Coordinatesजो 50:45 से शुरू होता है।


5

हां, यह iOS8 में ओरिएंटेशन-डिपेंडेंट है।

यहां बताया गया है कि आप एसडीके और ओएस-संस्करणों में एक iOS 8 फैशन में सीमा को पढ़ने का एक सुगम तरीका कैसे कर सकते हैं।

#ifndef NSFoundationVersionNumber_iOS_7_1
# define NSFoundationVersionNumber_iOS_7_1 1047.25
#endif

@implementation UIScreen (Legacy)

// iOS 8 way of returning bounds for all SDK's and OS-versions
- (CGRect)boundsRotatedWithStatusBar
{
    static BOOL isNotRotatedBySystem;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        BOOL OSIsBelowIOS8 = [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0;
        BOOL SDKIsBelowIOS8 = floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1;
        isNotRotatedBySystem = OSIsBelowIOS8 || SDKIsBelowIOS8;
    });

    BOOL needsToRotate = isNotRotatedBySystem && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
    if(needsToRotate)
    {
        CGRect screenBounds = [self bounds];
        CGRect bounds = screenBounds;
        bounds.size.width = screenBounds.size.height;
        bounds.size.height = screenBounds.size.width;
        return bounds;
    }
    else
    {
        return [self bounds];
    }
}

@end

1
SDK संस्करण की जाँच के साथ-साथ सहकर्मियों के मामले में एक अच्छी टिप है, SDK के विभिन्न संस्करणों के साथ आपके ऐप का निर्माण कर रहे हैं (हालाँकि ऐसा नहीं होना चाहिए!)।
क्रेग मैकमोहन

4

मेरा समाधान MaxK और hfossli का एक संयोजन है। मैंने इस विधि को यूआईस्क्रीन की श्रेणी में बनाया है और इसका कोई संस्करण जांच नहीं है (जो एक बुरा अभ्यास है):

//Always return the iOS8 way - i.e. height is the real orientation dependent height
+ (CGRect)screenBoundsOrientationDependent {
    UIScreen *screen = [UIScreen mainScreen];
    CGRect screenRect;
    if (![screen respondsToSelector:@selector(fixedCoordinateSpace)] && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        screenRect = CGRectMake(screen.bounds.origin.x, screen.bounds.origin.y, screen.bounds.size.height, screen.bounds.size.width);
    } else {
        screenRect = screen.bounds;
    }

    return screenRect;
}

3

मुझे एक त्वरित सहायक फ़ंक्शन की आवश्यकता थी जो iOS8 के तहत iOS7 के समान व्यवहार रखता था - इससे मुझे अपने [[UIScreen mainScreen] bounds]कॉल को स्वैप करने और अपने कोड को छूने की अनुमति नहीं मिली ...

+ (CGRect)iOS7StyleScreenBounds {
    CGRect bounds = [UIScreen mainScreen].bounds;
    if (([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        bounds.size = CGSizeMake(bounds.size.height, bounds.size.width);
    }
        return bounds;
}

बुरा, लेकिन समय पर काम पूरा होने तक चीजों को ठीक करने में लगाया जा सकता है :-)
DuneCat

3

नीचे दिए गए विधि का उपयोग किसी दिए गए अभिविन्यास के लिए स्क्रीन सीमा को खोजने के लिए किया जा सकता है, जो कि iOS संस्करण से स्वतंत्र है। यह विधि डिवाइस के स्क्रीन आकार के आधार पर सीमाएं लौटाएगी और iOS संस्करण से स्वतंत्र CGRect मान देगी।

- (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation {

    CGFloat width   = [[UIScreen mainScreen] bounds].size.width;
    CGFloat height  = [[UIScreen mainScreen] bounds].size.height;

    CGRect bounds = CGRectZero;

    if (UIInterfaceOrientationIsLandscape(orientation)) {
        bounds.size = CGSizeMake(MAX(width, height), MIN(width, height));
    } else {
        bounds.size = CGSizeMake(MIN(width, height), MAX(width, height));
    }

    return bounds;
}

// For the below example, bounds will have the same value if you run the code on iOS 8.x or below versions.
CGRect bounds = [self boundsForOrientation:UIInterfaceOrientationPortrait]; 

1

सही आयत की गणना के लिए मैंने जो प्रयोग किया था, वह है:

UIScreen* const mainScreen = [UIScreen mainScreen];
CGRect rect = [mainScreen bounds];
#ifdef __IPHONE_8_0
if ([mainScreen respondsToSelector:@selector(coordinateSpace)])
{
    if ([mainScreen respondsToSelector:@selector(fixedCoordinateSpace)])
    {
        id tmpCoordSpace = [mainScreen coordinateSpace];
        id tmpFixedCoordSpace = [mainScreen fixedCoordinateSpace];

        if ([tmpCoordSpace respondsToSelector:@selector(convertRect:toCoordinateSpace:)])
        {
            rect = [tmpCoordSpace convertRect:rect toCoordinateSpace: tmpFixedCoordSpace];
        }
    }
}
#endif

1

बस ऊपर दिए गए एक उत्कृष्ट cbartel फ़ंक्शन के स्विफ्ट संस्करण को जोड़ना।

func screenSize() -> CGSize {
    let screenSize = UIScreen.mainScreen().bounds.size
    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
        return CGSizeMake(screenSize.height, screenSize.width)
    }
    return screenSize
}

1

मेरा मुद्दा UIWindows फ्रेम से संबंधित था जो माइनस में जा रहा था। इसलिए नीचे दिए गए कोड को MyViewController - (NSUInteger) समर्थितInterfaceOrientations विधि के रूप में बनाया गया है

[[UIApplication sharedApplication] setStatusBarHidden:NO];

[self.view setFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];

[appDel.window setFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];

और मेरे लिए इसका काम यह कोशिश करना है।


1

iOS 8 या ऊपरी

उन लोगों के लिए एक समाधान जो अंक में स्क्रीन आकार का पता लगाना चाहते हैं (3.5 इंच स्क्रीन में 320 × 480 अंक हैं, 4.0 इंच स्क्रीन में 320 × 568 अंक हैं, आदि)

- (CGSize)screenSizeInPoints
{
    CGFloat width = [[UIScreen mainScreen] bounds].size.width;
    CGFloat height = [[UIScreen mainScreen] bounds].size.height;

    if (width > height) {
        return CGSizeMake(height, width);
    }
    else {
        return [[UIScreen mainScreen] bounds].size;
    }
}

0

एक बात जो मैंने नोट की है, Info.plist में समर्थित इंटरफ़ेस ओरिएंटेशन का क्रम मायने रखता है। मुझे इस प्रश्न की समस्या अपने ऐप के साथ मिली (जो कोड में ओरिएंटेशन करता है), लेकिन मैंने कहीं भी यह निर्दिष्ट नहीं किया कि डिफ़ॉल्ट ओरिएंटेशन पोर्ट्रेट है।

मुझे लगा कि किसी भी मामले में डिफ़ॉल्ट अभिविन्यास पोर्ट्रेट था

Info.plist में Rearranging itens, पहले Portrait लगाकर, अपेक्षित व्यवहार बहाल किया।


0

यह iOS7 और iOS8 दोनों में सही डिवाइस देगा ,

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define IS_PORTRAIT         UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)

+ (BOOL)isIPHONE4{

// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

        if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 480.0) {
            return YES;
        } else {
            return NO;
        }

// >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 480.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 480.0 && [self getDeviceHeight] == 320.0) {
            return YES;
        } else {
            return NO;
        }

    }

}


}

+ (BOOL)isIPHONE5{


// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

    if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 568.0) {
        return YES;
    } else {
        return NO;
    }

    // >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 568.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 568.0 && [self getDeviceHeight] == 320.0) {
            return YES;
        } else {
            return NO;
        }

    }

}

}

+ (BOOL)isIPHONE6{

// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

    if ([self getDeviceWidth] == 375.0 && [self getDeviceHeight] == 667.0) {
        return YES;
    } else {
        return NO;
    }

    // >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 375.0 && [self getDeviceHeight] == 667.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 667.0 && [self getDeviceHeight] == 375.0) {
            return YES;
        } else {
            return NO;
        }

    }

}


}
+ (BOOL)isIPHONE6Plus{


// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

    if ([self getDeviceWidth] == 414.0 && [self getDeviceHeight] == 736.0) {
        return YES;
    } else {
        return NO;
    }

    // >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 414.0 && [self getDeviceHeight] == 736.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 736.0 && [self getDeviceHeight] == 414.0) {
            return YES;
        } else {
            return NO;
        }

    }

}


}

+ (CGFloat)getDeviceHeight{

//NSLog(@"Device width: %f",[UIScreen mainScreen].bounds.size.height);
return [UIScreen mainScreen].bounds.size.height;
}
+ (CGFloat)getDeviceWidth{

//NSLog(@"Device width: %f",[UIScreen mainScreen].bounds.size.height);
return [UIScreen mainScreen].bounds.size.width;
}

// आप और अधिक डिवाइस (यानी आईपैड) जोड़ सकते हैं।


प्रश्न स्क्रीन रिज़ॉल्यूशन के आधार पर डिवाइस की पहचान के बारे में नहीं है। इसके अलावा Apple अनुकूली UI बनाने की सलाह देता है जो आकार वर्ग पर आधारित है न कि डिवाइस / स्क्रीन डिटेक्शन पर
जूलियन क्राल

0

मेनस्क्रीन सीमा पर न्यूनतम / अधिकतम का उपयोग करते हुए, iOS संस्करण की जांच के बिना, थोड़ा संशोधित mnemia के समाधान का उपयोग किया गया।
मैं एक की जरूरत है CGRectतो मिला CGRectmainscreen सीमा से और बदला size.width=min(w,h), size.height=max(w,h)। फिर मैंने CGRectअपने कोड में उस ओएस-इंडिपेंडेंट फंक्शन को दो जगहों पर बुलाया , जहाँ मुझे स्क्रीन साइज़ मिल रहा है OpenGL, टच करना आदि। फिक्स होने से पहले मुझे 2 प्रॉब्लम थीं - IOS 8.x पर लैंडस्केप मोड डिस्प्ले OpenGLव्यू की पोज़िशन गलत थी: 1 / 4 बायीं ओर के हिस्से में फुल स्क्रीन। और दूसरा स्पर्श अमान्य मान लौटाता है। दोनों समस्याओं को स्पष्ट किया गया। धन्यवाद!

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