2009-07-21 9 views
12

In meinem Programm verschiebe ich Dinge basierend auf Rotation, aber ich rotiere nicht die gesamte Ansicht. Ich verwende:Wie erkenne ich die iPhone-Ausrichtung vor dem Drehen?

static UIDeviceOrientation previousOrientation = UIDeviceOrientationPortrait; 

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
    [window addSubview:viewController.view]; 
    [window makeKeyAndVisible]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
      selector:@selector(didRotate:) 
      name:@"UIDeviceOrientationDidChangeNotification" object:nil]; 

} 

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

    [self doRotationStuff:orientation: previousOrientation]; 
previousOrientation = orientation; 

} 

Dies funktioniert solange, wenn das Programm gestartet wird, ist das Gerät Orientierung Porträt, aber nicht, wenn die anfängliche Orientierung ist Landschaft oder auf den Kopf, weil [self doRotationStuff] macht Änderungen relativ zum Unterschied von der vorherigen Orientierung.

Gibt es eine Möglichkeit, die Ausrichtung entweder beim Start oder direkt vor dem Drehen des Geräts zu erkennen?

Antwort

3

Aktualisiert:

Also, aus dem Kommentar Diskussion scheint es, dass Sie nicht auf [UIDevice currentDevice].orientation verlassen können, bis die Orientierung tatsächlich zum ersten Mal ändert. Wenn das der Fall ist, könnten Sie es wahrscheinlich hacken, indem Sie rohe Beschleunigungsmesserablesungen erhalten.

#define kUpdateFrequency 30 // Hz 
#define kUpdateCount 15 // So we init after half a second 
#define kFilteringFactor (1.0f/kUpdateCount) 

- (void)applicationDidFinishLaunching:(UIApplication *)app 
{ 
    [UIAccelerometer sharedAccelerometer].updateInterval = (1.0/kUpdateFrequency); 
    [UIAccelerometer sharedAccelerometer].delegate = self; 
    accelerometerCounter = 0; 
    ... 
} 

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)accel 
{ 
    // Average out the first kUpdateCount readings 
    // acceleration_[xyz] are ivars typed float 
    acceleration_x = (float)accel.x * kFilteringFactor + acceleration_x * (1.0f - kFilteringFactor); 
    acceleration_y = (float)accel.y * kFilteringFactor + acceleration_y * (1.0f - kFilteringFactor); 
    acceleration_z = (float)accel.z * kFilteringFactor + acceleration_z * (1.0f - kFilteringFactor); 

    accelerometerCounter++; 
    if (accelerometerCounter == kUpdateCount) 
    { 
     [self initOrientation]; 
     [UIAccelerometer sharedAccelerometer].delegate = nil; 
    } 
} 

- (void)initOrientation 
{ 
    // Figure out orientation from acceleration_[xyz] and set up your UI... 
} 

Ursprüngliche Antwort:

Ist die richtige Ausrichtung während applicationDidFinishLaunching:[UIDevice currentDevice].orientation zurückkehren? Wenn dies der Fall ist, können Sie Ihre ursprüngliche Benutzeroberfläche entsprechend dieser Ausrichtung einrichten.

Wenn diese Eigenschaft erst zu einem späteren Zeitpunkt aktiviert wird, können Sie nach einer kurzen Verzögerung mit performSelector:afterDelay: experimentieren, um die Benutzeroberfläche zu initialisieren.

Dieses Codebeispiel von Kendall ist unten Antwort, hier der Vollständigkeit halber hinzugefügt:

[self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f]; 

Ich bin mir nicht sicher, ob eine Null-Sekunden-Verzögerung, die ausreichend ist - dies bedeutet, dass der Code für getOriented während des Laufes wird Durchlauf durch die Ereignislaufschleife. Möglicherweise müssen Sie länger warten, bis die Messwerte des Beschleunigungsmessers unter registriert werden.

+0

Während applicationDidFinishLaunching [UIDevice currentDevice] .orientation ist UIDeviceOrientationUnknown –

+0

Ich bin ratlos, wie ich perform verwenden würde: afterDelay. Können Sie ein Codebeispiel geben? –

+0

Ich habe versucht, was Sie sagten, aber auch [self performSelector: @selector (getOriented) withObject: nil afterDelay: 10.0f]; hatte keinen Effekt –

-1

Als Antwort auf Ihren Kommentar, dachte ich, ich besseren Code hier als in einem Kommentar setzen könnte (obwohl wirklich Daniel Kredit hier verdient):

in applicationDidFinishLaunching:

[self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f]; 

Dann brauchen Sie nur die Methode aufzurufen:

- (void) getOriented 
{ 
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 
    // save orientation somewhere 
} 
+0

Ich habe versucht, was Sie sagten, aber auch [self performSelector: @selector (getOriented) withObject: nil afterDelay: 10.0f]; hatte keinen Effekt –

+0

Wie war die Ausrichtung, als es zehn Sekunden später aufgerufen wurde? Es scheint, als ob nach zehn Sekunden die Ausrichtung eingestellt sein sollte ... oder zu diesem Zeitpunkt einfach den Hauptansicht-Controller fragen, welche Ausrichtung er hat. –

+0

war es UIDeviceOrientationUnknown –

1

Mort, diese Antworten scheinen etwas von einem roten Hering; Ich kann nicht sehen, warum Sie nicht die folgende integrierte Methode für eine UIViewController-Klasse verwenden können:

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {} 

Diese Methode automatisch aufgerufen wird, nachdem eine Drehung (statt mit ShouldAutorotateToInterfaceOrientation aufgetreten ist, die man nur sagt es geht um passieren). Praktischerweise enthält die Variable 'fromInterfaceOrientation' die vorherige Ausrichtung. Wie die Dokumentation auch sagt, können Sie davon ausgehen, dass die Eigenschaft interfaceOrientation der Ansicht bereits auf die neue Ausrichtung gesetzt wurde. Sie haben also eine Methode mit Zugriff auf die alte Ausrichtung und die neue!

Wenn ich etwas verpasst habe und Sie bereits entlassen haben, entschuldigen Sie diese Methode! Es scheint nur seltsam, dass Sie eine Variable für die "vorherige Ausrichtung" erstellen und speichern, wenn sie in der obigen Methode kostenlos zur Verfügung gestellt wird.

Hoffe, dass hilft!

+0

Das würde funktionieren, wenn ich die Schnittstelle rotieren wollte, was ich nicht tun möchte. –

0

Ein vollständigeres Beispiel zur Ermittlung der Geräteausrichtung anhand von Beschleunigermessungen finden Sie unter Da die Lösung auf Beschleunigermessungen basiert, funktioniert sie im Simulator nicht, Sie müssen also am Gerät arbeiten. .. suche noch selbst nach einer Lösung, die am Simulator funktioniert.

12

Abhängig von Ihren Umständen ist eine einfachere Option möglicherweise die interfaceOrientation-Eigenschaft der UIViewController-Klasse. Dies ist vor einer Drehung korrekt.

+2

Danke! Ich wusste nicht, dass das Feld htat existierte - ich benutzte die Orientierung von UIDevice, was nicht sehr hilfreich war. – Chris

+0

Dies ist, warum *** S.O Rocks! ******************************************************************************************************************************************************************* –

1

Verwenden Sie dies für die Ausrichtung der Benutzeroberfläche, wenn Sie bestimmen müssen, auf welche Weise Sie zeigen.

nicht zu 100% sicher, das ist richtig, aber die Spitze von meinem Kopf abgehend:

[[[UIApplication sharedApplication] statusBar] orientation] 
1

Hier ein Weg, um die Orientierung zu erhalten, wenn die App zum ersten Mal geladen und die UIDeviceOrientation auf UIDeviceOrientationUnknown gesetzt. Sie können die transform-Eigenschaft der gedrehten Ansicht betrachten.

if(toInterface == UIDeviceOrientationUnknown) { 
    CGAffineTransform trans = navigationController.view.transform; 
    if(trans.b == 1 && trans.c == -1) 
     toInterface = UIDeviceOrientationLandscapeLeft; 
    else if(trans.b == -1 && trans.c == 1) 
     toInterface = UIDeviceOrientationLandscapeRight; 
    else if(trans.a == -1 && trans.d == -1) 
     toInterface = UIDeviceOrientationPortraitUpsideDown; 
    else 
     toInterface = UIDeviceOrientationPortrait; 
} 
+0

Das ist Gold! Es gibt Ihnen die Orientierung einer Ansicht. Ich benutzte dies mit 'UIDeviceOrientationDidChangeNotification', um meine vorherige Orientierung zu erkennen. – cnotethegr8

Verwandte Themen