Wie erkenne ich die Ausrichtung des Geräts unter iOS?

72

Ich habe eine Frage zum Erkennen der Geräteorientierung unter iOS. Ich muss keine Änderungsbenachrichtigungen erhalten, nur die aktuelle Ausrichtung. Dies scheint eine ziemlich einfache Frage zu sein, aber ich konnte meinen Kopf nicht darum wickeln. Folgendes habe ich bisher getan:

UIDevice *myDevice = [UIDevice currentDevice] ;
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation deviceOrientation = myDevice.orientation;
BOOL isCurrentlyLandscapeView = UIDeviceOrientationIsLandscape(deviceOrientation);
[myDevice endGeneratingDeviceOrientationNotifications];

In meinen Augen sollte das funktionieren. Ich aktiviere das Gerät, um Benachrichtigungen zur Geräteorientierung zu empfangen, und frage dann nach der Ausrichtung, in der es sich befindet. Dann funktioniert es jedoch nicht und ich weiß nicht warum.

JusmanX
quelle

Antworten:

120

Wirklich alter Thread, aber keine echte Lösung.

Ich hatte das gleiche Problem, stellte jedoch fest, dass das Abrufen der UIDeviceOrientation nicht immer konsistent ist. Verwenden Sie stattdessen Folgendes:

UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;

if(orientation == 0) //Default orientation 
    //UI is in Default (Portrait) -- this is really a just a failsafe. 
else if(orientation == UIInterfaceOrientationPortrait)
    //Do something if the orientation is in Portrait
else if(orientation == UIInterfaceOrientationLandscapeLeft)
    // Do something if Left
else if(orientation == UIInterfaceOrientationLandscapeRight)
    //Do something if right
Moe
quelle
5
Dies ist die richtigste Antwort, wenn ich darf. Auf diese Weise können Sie die Ausrichtung der Benutzeroberfläche jederzeit abrufen, indem Sie einfach diese Eigenschaft überprüfen. Beachten Sie, dass es keine Rolle spielt, ob die Statusleiste ausgeblendet ist oder nicht, die Eigenschaft wird auf jeden Fall aktualisiert!
Ktolis
3
Wenn Sie wählerisch sind und sich nicht auf die Ausfallsicherheit verlassen möchten, vergessen Sie nicht UIInterfaceOrientationPortraitUpsideDown.
ArkReversed
Dies funktioniert bei mir, außer dass das Porträt überhaupt nicht erkannt wurde. Ich musste erkennen, ob es rechts oder links war, und dann, wenn es keines war, es als Porträt behandeln.
Marcel Marino
4
Dies funktioniert nicht, wenn die Ausrichtung der Anwendung entweder auf den Hochformat- oder den Querformatmodus beschränkt ist.
Salman Khakwani
In meinem Fall funktioniert es nicht, es gibt immer ein Porträt zurück. Ich habe die P-Liste geändert, um mehrere Ausrichtungen zu akzeptieren. Weiß jemand warum?
ZijunLost
76

wenn UIViewController:

if (UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
    // 
}

wenn UIView:

if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
    //
}

UIDevice.h:

#define UIDeviceOrientationIsPortrait(orientation)  ((orientation) == UIDeviceOrientationPortrait || (orientation) == UIDeviceOrientationPortraitUpsideDown)
#define UIDeviceOrientationIsLandscape(orientation) ((orientation) == UIDeviceOrientationLandscapeLeft || (orientation) == UIDeviceOrientationLandscapeRight)

Aktualisiert :

Fügen Sie diesen Code zu xxx-Prefix.pch hinzu, dann können Sie ihn überall verwenden:

// check device orientation
#define dDeviceOrientation [[UIDevice currentDevice] orientation]
#define isPortrait  UIDeviceOrientationIsPortrait(dDeviceOrientation)
#define isLandscape UIDeviceOrientationIsLandscape(dDeviceOrientation)
#define isFaceUp    dDeviceOrientation == UIDeviceOrientationFaceUp   ? YES : NO
#define isFaceDown  dDeviceOrientation == UIDeviceOrientationFaceDown ? YES : NO

Verwendung:

if (isLandscape) { NSLog(@"Landscape"); }
TONy.W
quelle
1
Dies ist eine sehr gute Antwort. Ich habe die Dokumentation noch einmal überprüft - mehr noch, es ist eine großartige Antwort, es ist unter dem Gesichtspunkt der Richtigkeit eine richtige. Verdient, als geprüft markiert zu werden.
Dumoko
1
Dies ist alles, was ich jemals in einer Erklärung zur Bestimmung der Geräteorientierung wollte. Danke TONy. W
Morkrom
Interessanterweise scheint nur 'isLandscape' auf meinem iPad-Simulator korrekt zu feuern (alle anderen geben unabhängig davon NEIN zurück). Ich hatte noch keine Gelegenheit, meine echte Hardware zu testen ... aber ich liebe Ihren Ansatz. Danke.
BonanzaDriver
1
UIViewController::interfaceOrientationkehrt zurück UIInterfaceOrientation, während a UIDeviceOrientationIsLandscapeakzeptiert wird UIDeviceOrientation. Dies mag heute funktionieren, ist aber nicht vorwärtskompatibel.
Pwner
1
'interfaceOrientation' ist veraltet: zuerst veraltet in iOS 8.0
Bill Chan
22

Für das, wonach Sie zuerst suchen, müssen Sie eine Benachrichtigung erhalten, wenn sich die Ausrichtung ändert! Sie können diese Sache in viewDidLoad wie einstellen

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];

und wann immer sich die Ausrichtung Ihres Geräts ändert OrientationDidChange Wird aufgerufen, wo Sie je nach Ausrichtung tun können, was Sie wollen

-(void)OrientationDidChange:(NSNotification*)notification
{
    UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];

    if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight)
    {
    }
    else if(Orientation==UIDeviceOrientationPortrait)
    {
    }
}
Saurabh Prajapati
quelle
1
Dies funktioniert tatsächlich perfekt für mich, da ich diese Informationen nur in einem ViewController benötige. Der Rest der App sollte die Ausrichtung nicht ändern. Also vielen Dank!
CarmenA
22

Wenn Sie die Geräteorientierung direkt vom Beschleunigungsmesser erhalten möchten, verwenden Sie diese [[UIDevice currentDevice] orientation]. Wenn Sie jedoch die aktuelle Ausrichtung Ihrer Anwendung ( Schnittstellenausrichtung ) benötigen, verwenden Sie [[UIApplication sharedApplication] statusBarOrientation].

Rafalkitta
quelle
9

UIViewControllerverfügt über eine interfaceOrientationEigenschaft, auf die Sie zugreifen können, um die aktuelle Ausrichtung eines Ansichtscontrollers zu ermitteln.

Was Ihr Beispiel betrifft, sollte das funktionieren. Was meinst du, wenn du sagst, dass es nicht funktioniert? Welche Ergebnisse erzielen Sie im Vergleich zu Ihren Erwartungen?

Jasarien
quelle
1
Ich habe es im iOS-Simulator debuggt und unabhängig von der Ausrichtung des Geräts wird immer NEIN zurückgegeben. Wenn ich einen Haltepunkt darauf setze, stelle ich fest, dass die Ausgabe von deviceOrientation = myDevice.orientation immer UIDeviceOrientationUnknown ist, sodass es nicht so aussieht, als würde die Ausrichtung richtig verfolgt.
JusmanX
8

In Swift 3.0

um die Geräteorientierung zu erhalten.

/* return current device orientation.
   This will return UIDeviceOrientationUnknown unless device orientation notifications are being generated. 
*/
UIDevice.current.orientation

um die Geräteorientierung von Ihrer App zu erhalten

UIApplication.shared.statusBarOrientation
Ashok R.
quelle
2
"'statusBarOrientation' war in iOS 13.0 veraltet: Verwenden Sie stattdessen die Eigenschaft interfaceOrientation der Fensterszene." Hier ist die Referenz stackoverflow.com/questions/25796545/…
Egel
4

Wurde von "UIDeviceOrientation" nicht zufriedengestellt, da Sie, wenn eine UIViewcontroller-Ausrichtung auf eine bestimmte Ausrichtung festgelegt ist, keine relevanten Informationen zur Geräteorientierung erhalten . Verwenden Sie daher "UIInterfaceOrientation" .

Sie können die Ausrichtung vom UIViewController mit einer "self.interfaceOrientation" abrufen. Wenn Sie jedoch unseren Code faktorisieren, müssen Sie diese Art von Test möglicherweise außerhalb eines Ansichtscontrollers durchführen (benutzerdefinierte Ansicht, eine Kategorie ...), damit Sie immer noch Sie können mit dem rootviewController überall außerhalb des Controllers auf die Informationen zugreifen :

if (UIInterfaceOrientationIsLandscape(view.window.rootViewController.interfaceOrientation)) {
}
Nicolas Lauquin
quelle
2

Es gibt eine Möglichkeit, dies zu erreichen, unabhängig davon, ob die Orientierungssperre aktiviert ist oder nicht, indem Daten von CoreMotion verwendet werden. Dies ist der Code:

#import <CoreMotion/CoreMotion.h> 

    CMMotionManager *cm=[[CMMotionManager alloc] init];
    cm.deviceMotionUpdateInterval=0.2f;
    [cm startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
                            withHandler:^(CMDeviceMotion *data, NSError *error) {

                            if(fabs(data.gravity.x)>fabs(data.gravity.y)){
                                    NSLog(@"LANSCAPE");
                                if(data.gravity.x>=0){
                                    NSLog(@"LEFT");
                                }
                                else{
                                    NSLog(@"RIGHT");
                                }

                        }
                        else{
                                NSLog(@"PORTRAIT");
                                if(data.gravity.y>=0){
                                    NSLog(@"DOWN");
                                }
                                else{

                                    NSLog(@"UP");
                                }

                            }

}];
FlySoFast
quelle
1

Haben Sie die Hardware-Sperre zur Geräteorientierung entsperrt? Es gibt eine am Rand meines iPad 1.

Martin Lütke
quelle
aber es funktioniert schon nicht im iOS-Simulator ... Ich stelle es noch nicht einmal auf das Gerät.
JusmanX
@JusmanX Es gibt eine verwandte Frage bei SO: uidevice-currentdevice-Orientierung-immer-null
Martin Lütke
1

Hier sind einige Swift-Variablen, um die Erkennung zu vereinfachen:

let LANDSCAPE_RIGHT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight
let LANDSCAPE_LEFT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft
let LANDSCAPE: Bool = LANDSCAPE_LEFT || LANDSCAPE_RIGHT
let PORTRAIT_NORMAL: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.Portrait
let PORTRAIT_REVERSE: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.PortraitUpsideDown
let PORTRAIT: Bool = PORTRAIT_REVERSE || PORTRAIT_NORMAL
Beninho85
quelle
0

Meine derzeitige Vorgehensweise:

+ (BOOL)isPortrait {
    let window = UIApplication.sharedApplication.delegate.window;
    if(window.rootViewController) {
        let orientation =
        window.rootViewController.interfaceOrientation;
        return UIInterfaceOrientationIsPortrait(orientation);
    } else {
        let orientation =
        UIApplication.sharedApplication.statusBarOrientation;
        return UIInterfaceOrientationIsPortrait(orientation);
    }
}

Wenn es aus irgendeinem Grund noch keinen rootViewController gibt, ist die StatusBarOrientation noch nicht sicher ...

Renetik
quelle
0

Und der beste zuverlässige Weg in Kürze:

public extension UIScreen {

    public class var isPortrait: Bool {
        UIApplication.shared.delegate?.window??.rootViewController?.interfaceOrientation.isPortrait ??
                UIApplication.shared.statusBarOrientation.isPortrait
    }

    public class var isLandscape: Bool { !isPortrait }
}
Renetik
quelle