Wird [UIScreen mainScreen] .bounds.size in iOS8 orientierungsabhängig?


184

Ich habe den folgenden Code sowohl in iOS 7 als auch in iOS 8 ausgeführt:

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

Folgendes ist das Ergebnis von iOS 8:

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

Im Vergleich zum Ergebnis in iOS 7:

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

Gibt es eine Dokumentation, die diese Änderung spezifiziert? Oder ist es ein vorübergehender Fehler in iOS 8-APIs?


13
Nun, die iOS8-Ausgabe scheint viel logischer
Levi

Antworten:


173

Ja, es ist orientierungsabhängig in iOS8, kein Fehler. Weitere Informationen finden Sie in Sitzung 214 der WWDC 2014: "Erweiterungen des Controllers in iOS 8 anzeigen"

Zitat aus der Präsentation:

UIScreen ist jetzt schnittstellenorientiert:

  • [UIScreen-Grenzen] jetzt schnittstellenorientiert
  • [UIScreen applicationFrame] jetzt schnittstellenorientiert
  • Rahmenbenachrichtigungen in der Statusleiste sind schnittstellenorientiert
  • Tastaturrahmenbenachrichtigungen sind schnittstellenorientiert

7
In der oben erwähnten WWDC-Vorlesung beginnt der schnittstellenorientierte Teil um 51:50 Uhr.
cnotethegr8

2
Ich habe den größten Teil des heutigen Tages damit verbracht, diesen Fortschritt zu umgehen. Anscheinend passiert das nicht immer. Wenn Sie also Entwickler eines SDK sind, das in anderen Anwendungen arbeiten muss, ist dieses Zeug noch komplizierter geworden.
Glenn Maynard

1
@aroth Sie können nicht innovativ sein, ohne einige alte Gewohnheiten zu bremsen.
Boris Y.

23
@borisy - Ich bin respektvoll anderer Meinung. In den meisten Fällen ist es möglich, Innovationen bei gleichzeitiger Wahrung der Abwärtskompatibilität durchzuführen. Veränderungen zu brechen ist meiner Meinung nach mehr als alles andere ein Hauch von Faulheit. Sie wollen, dass alle anderen die Arbeit machen.
aroth

1
Diese Antwort wäre noch hilfreicher, wenn erklärt würde, was schnittstellenorientiert eigentlich bedeutet. Ich kann mich irren, aber ich denke, die Orientierungsabhängigkeit betrifft nur View Controller. Wenn Sie eine andere Klasse nehmen und die Grenzen berechnen, entsprechen diese immer noch dem alten Stil, immer im Hochformat.
Maxi Mus

59

Ja, es ist orientierungsabhängig in iOS8.

Ich habe eine Util-Methode geschrieben, um dieses Problem für Apps zu beheben, die ältere Versionen des Betriebssystems unterstützen müssen.

+ (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
Ich habe den Code bearbeitet, bitte überprüfen Sie, Ihre Bedingung für die Überprüfung der Betriebssystemversion war falsch
Jageen

@ Jageen Bitte klären Sie, die Versionsprüfung funktioniert bei mir. Was ist das Problem?
Cbartel

Was ich verstehe ist, wir müssen Höhe und Breite ändern, wenn das Betriebssystem iOS8 ist und die Ausrichtung Querformat ist. Habe ich recht?
Jageen

@Jageen Negativ, in iOS 8 ist die Methode orientierungsabhängig. Ihre Logik ist umgeschaltet. Ihre Bearbeitung wurde korrekt abgelehnt.
Cbartel

@cbartel Gibt es eine Möglichkeit, dies in UIScreen zu kategorisieren, sodass unser ursprünglicher Aufruf von [UIScreen mainScreen] .bounds.size sowohl für iOS 7 als auch für iOS 8 funktioniert?
Kevinl

34

Ja, tatsächlich hängt die Bildschirmgröße jetzt in iOS 8 von der Ausrichtung ab. Manchmal ist es jedoch erwünscht, eine Größe festzulegen, die auf die Hochformatausrichtung festgelegt ist. Hier ist, wie ich es mache.

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

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

2
Ich stelle fest, dass dies das Problem mit normalen iPhone-Apps behebt, jedoch nicht mit iPhone-Apps, die auf dem iPad ausgeführt werden.
ThomasW

32

Ja, es hängt jetzt von der Orientierung ab.

Ich bevorzuge die folgende Methode, um die Bildschirmgröße orientierungsunabhängig zu ermitteln, gegenüber einigen der obigen Antworten, sowohl weil sie einfacher ist als auch weil sie nicht von einem der Orientierungscodes abhängt (deren Status von der abhängen kann Zeitpunkt, zu dem sie aufgerufen werden) oder bei der Versionsprüfung. Möglicherweise möchten Sie das neue Verhalten von iOS 8, dies funktioniert jedoch, wenn es auf allen iOS-Versionen stabil sein muss.

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

Funktioniert wahrscheinlich nicht mit Apple TV, wo es (fast) immer breiter als groß ist.
cbh2000

11

Im Zusammenhang mit dieser Frage, die mein Problem gelöst hat, werden hier zwei Definitionen für die Berechnung der Bildschirmbreite und -höhe verwendet:

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

Wenn Sie sowohl iOS 7 als auch iOS 8 unterstützen, ist dies die beste Lösung für dieses Problem.


@Namit Gupta, deine Bearbeitung ist falsch. Wenn die IOS-Version 8 oder höher ist, können wir die UIScreen-Dimensionen verwenden, da diese orientierungsabhängig sind. Vor iOS 8 mussten Sie die Ausrichtung der Statusleiste überprüfen. Ihre Bearbeitung besagt nun, dass alle iOS-Versionen, die nicht niedriger als 8 sind, die Ausrichtung der Statusleiste überprüfen sollten, was falsch ist.
Antoine

9

Sie können verwenden nativeBounds(orientierungsunabhängig)

nativeBounds

Das Begrenzungsrechteck des physischen Bildschirms, gemessen in Pixel. (schreibgeschützt)

Erklärung SWIFT

  var nativeBounds: CGRect { get }

Dieses Rechteck basiert auf dem Gerät im Hochformat. Dieser Wert ändert sich nicht, wenn sich das Gerät dreht.

Erkennen der Gerätehöhe:

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

}

Erkennen der Gerätebreite:

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

}

3
Beachten Sie, dass diese Methode Pixel zurückgibt, während die meisten anderen Methoden Punkte behandeln. Ganz andere Dinge.
jcsahnwaldt Reinstate Monica

1
In meinem Fall genau das, was ich brauchte :) (OpenGL oder andere Ansichten, die nicht auf UIViews basieren, aber wo ich die genauen
Pixelabmessungen

3
Warnung: auf dem iPhone 6+ gab dies 1080 x 1920 zurück, was möglicherweise nicht das ist, was Sie wollen
Chanon

8

Es ist kein Fehler im iOS 8 SDK. Sie machten die Ausrichtung der Grenzflächen abhängig. Aufgrund Ihrer Frage zu einem Verweis oder einer Dokumentation zu dieser Tatsache empfehle ich Ihnen dringend View Controller Advancements in iOS 8, sich die 214-Sitzung der WWDC 2014 anzusehen . Der interessanteste Teil (Ihrer Zweifel nach) ist Screen Coordinatesder, der um 50:45 Uhr beginnt.


5

Ja, es ist orientierungsabhängig in iOS8.

Hier erfahren Sie, wie Sie Grenzen auf konsistente Weise in iOS 8 für SDKs und Betriebssystemversionen auslesen können.

#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
Das Überprüfen der SDK-Version ist auch ein guter Tipp für den Fall, dass Kollegen Ihre App mit unterschiedlichen Versionen des SDK erstellen (obwohl dies nicht passieren sollte!).
Craig McMahon

4

Meine Lösung ist eine Kombination aus MaxKs und hfossli. Ich habe diese Methode in einer Kategorie von UIScreen erstellt und es gibt keine Versionsprüfungen (was eine schlechte Praxis ist):

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

Ich brauchte eine schnelle Hilfsfunktion, die unter iOS8 das gleiche Verhalten wie iOS7 beibehielt - so konnte ich meine [[UIScreen mainScreen] bounds]Anrufe austauschen und keinen anderen Code berühren ...

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

Böse, aber erledigt den Job, bis die Zeit gekommen ist, um die Dinge richtig zu reparieren :-)
DuneCat

3

Die folgende Methode kann verwendet werden, um die Bildschirmgrenzen für eine bestimmte Ausrichtung unabhängig von der iOS-Version zu ermitteln. Diese Methode gibt die Grenzen basierend auf der Bildschirmgröße des Geräts zurück und gibt unabhängig von der iOS-Version denselben CGRect-Wert aus.

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

Das habe ich verwendet, um das richtige Rect zu berechnen:

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

Fügen Sie einfach die schnelle Version einer hervorragenden Cbartel-Funktion hinzu, die oben beantwortet wurde.

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

Mein Problem bezog sich auf den UIWindows-Frame, der in Minus ging. So machte der Code wie folgt in MyViewController - (NSUInteger) unterstützteInterfaceOrientations-Methode

[[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)];

Und seine Arbeit für mich versuchen es.


1

iOS 8 oder höher

Eine Lösung für diejenigen, die die Bildschirmgröße in Punkten herausfinden möchten (3,5-Zoll-Bildschirm hat 320 × 480 Punkte, 4,0-Zoll-Bildschirm hat 320 × 568 Punkte usw.) wäre

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

Eine Sache, die ich bemerkt habe, ist, dass die Reihenfolge der unterstützten Schnittstellenausrichtungen in Info.plist eine Rolle spielt. Ich habe das Problem dieser Frage mit meiner App (die die Ausrichtung im Code ausführt), aber ich habe nirgendwo angegeben, dass die Standardausrichtung Porträt ist.

Ich dachte , dass Standardausrichtung war Portrait auf jeden Fall.

Durch das Neuanordnen von itens in Info.plist, wobei Portrait an erster Stelle steht, wurde das erwartete Verhalten wiederhergestellt.


0

Dies wird richtiges Gerät in geben iOS7 und iOS8 beide,

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

// Sie können auch weitere Geräte hinzufügen (ieiPad).


Bei der Frage geht es nicht um die Geräteerkennung basierend auf der Bildschirmauflösung. Darüber hinaus empfiehlt Apple, eine adaptive Benutzeroberfläche zu erstellen, die auf Größenklassen basiert, die nicht auf der Geräte- / Bildschirmerkennung basieren
Julian Król,

0

Verwendete leicht modifizierte Mnemia-Lösung, die ohne iOS-Versionsprüfung verwendet wurde, wobei min / max auf den Grenzen des Hauptbildschirms verwendet wurde.
Ich brauchte eine CGRectso CGRectvom Hauptbildschirm entfernte und veränderte size.width=min(w,h), size.height=max(w,h). Dann habe ich diese OS-unabhängige Get- CGRectFunktion an zwei Stellen in meinem Code aufgerufen , an denen ich die Bildschirmgröße OpenGL, Berührungen usw. erhalten habe. Vor der Behebung hatte ich zwei Probleme - unter IOS 8.x im Querformat war die Anzeigeposition der OpenGLAnsicht falsch: 1 / 4 des Vollbildes im linken unteren Teil. Und zweite Berührungen gaben ungültige Werte zurück. Beide Probleme wurden wie erläutert behoben. Vielen Dank!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.