Frage

UPDATE: Siehe meine Antwort zunächst auf diese Frage. Dies scheint ein Fehler zu sein. Ein minimaler Testfall wurde erstellt und ein Bericht mit Apple eingereicht. (Fixed ab iPhone OS 3.1.)

Hier ist ein Puzzler aus der „Ich bin so nah!“ Abteilung.

Ich habe ein Tab Bar-basiertes iPhone-App. Jeder Reiter verfügt über ein UINavigationController mit den üblich Verdächtigen (nav bar, Tabellenansicht ... die wiederum zu einem anderen VC führen, usw.).

Nun, eine dieser unteren Ebene VCs ist in Portait verwendet werden und Querformat. Aber es gibt ein Problem. Unsere Landschaft freundliche VC ShouldAutorotateToInterfaceOrientation: erhalten out-of-the-box nicht genannt! Was ist zu tun?

Hier ist, was wir tun. In meinen Tab Bar-Controller, die ich in einer eigenen Datei implementiert habe, ich habe dies:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

Dieses endet die Anfrage an meine Landschaft freundliche VC propagieren, die auch auf diese Nachricht reagiert. Alle meine andere VCs haben diese Methode nicht implementieren, so dass sie einfach mit dem Standard-Hochformat gehen.

Problem gelöst !!! Yay!

Nun, nicht ganz :. (

Scheint, wie die Dinge nicht so gut, wenn meine Landschaft freundliche VC aus den Tiefen des Controllers Tab-Leiste aufgerufen wird MoreNavigationController .

Ich entschied / vergleichen Kontrast zwischen einem VC genannt aus einer der ersten vier Tab-Leiste UINavigationControllers ... und das gleiche VC genannt innerhalb der MoreNavigationController . Das wird ein bisschen extrem detailliert sein, so mit mir tragen. Hoffentlich wird das Spiel durch Spiel erweist sich als nützlich für sleuthing Dinge aus.

Wenn die App geladen wird, gibt es mehrere anfängliche Anrufe auf die Tab-Leiste Controller shouldAutorotate ... Methode. In diesen frühen Fällen selectedViewController ist gleich Null. Allerdings haben wir schließlich Laden beenden, das anfängliche Registerkarte Element ausgewählt ist, und alles ist gut.

Richtig. Lassen Sie uns zunächst einen der ersten vier Tableiste Artikel auswählen und in unseren VC Drilldown.

Wir werden dritte Navigationsleiste Einzelteil auswählen, das ist also der dritte nav-Controller. Wir bohren, um unsere VC nach unten, die Rotation unterstützt. Eine schnelle Inspektion bestätigt, dass der Elternteil ist in der Tat die dritten nav-Controller aus unserer Tab-Leiste der View-Controller-Liste. Gut!

Lassen Sie uns das Gerät drehen. Die Tab-Leiste Controller wird gebeten (siehe den obigen Code) autorotate. Wir beobachten, dass selectedViewController ist auch, dass dritte nav-Controller sowie die oberen und sichtbaren Ansicht des nav-Controller Controller beide auf unsere treuen VC sind, die Rotation unterstützt.

So wird die Tab-Leiste Controller leitet die shouldAutorotate Nachricht über auf die dritten nav-Controller ... aber unsere Rotation freundliche VC wird schließlich die Nachricht. (Ich nichts zu tun Besonderes hier. Vielleicht ist die gewünschte VC die Nachricht bekommt, weil es die oberen und / oder sichtbar VC ist?) Auf jeden Fall drehen wir Landschaft, sind Dinge, die Größe neu bestimmt, und alles ist gut. "Großer Erfolg!"

Lassen Sie sich jetzt, dass Hit-Taste zurück und den VC-Stack Pop, Landscape-Modus in dem Prozess zu verlassen. Die Tab-Leiste Controller abgefragt wieder.

Zeit für ein beiseite hier wenig. Die topViewController für unsere nav-Controller ist nach wie vor, dass die Rotation freundliche VC, aber visibleViewController ist nun auf UISnapshotModalViewController ! Heh. Nie sah diese ein, bevor ... aber Erica Sadun hat. Sieht aus wie es für „verschwindet View-Controller“ ist. (Was in diesem Fall sicherlich richtig - es verschwindet in Ordnung)

Wie ich halten Schreiten durch, bleibt der sichtbare VC als Snapshot, aber die Top-VC ändert sich schließlich auf die nächste VC auf dem Stack, da meine speziellen VC schließlich verschwunden. Fair enough.

So das ist das Szenario where alles gut funktioniert.

Lassen Sie sich nun den gleichen Test versuchen, nur dieses Mal, dass wir nach wie vor auf den MoreNavigationController (Mehr Tableiste Artikel) und Drill-Down auf die gleiche VC Klasse gehen werden. In meinem Fall kommt es der siebte ein in der Tab-Leiste Controller VC Liste.

Wir betreten die Rotation-aware VC und ... dieses Mal ist es gefragt wird drehen direkt ! Die Tab-Leiste Controller ist nicht bat um Erlaubnis, überhaupt zu drehen. Hmm.

Eine schnelle Überprüfung der Mutter VC zeigt es ist ein MoreNavigationController . OK, das macht Sinn.

Nun wollen wir versuchen, das Gerät zu drehen. Es wird nichts dem Namen . Keiner unserer Stützpunkte getroffen zu werden. Nicht in unserem VC. Nicht in unserer Tab-Leiste Controller. (Huh?!?!)

O-kaaaay. Lassen Sie uns den Stapel pop, gehen Sie zurück in die gleiche VC und versuchen Sie es erneut zu drehen. Seltsam. Jetzt sind wir für die Autorotation um Erlaubnis zu fragen einen Anruf in dem Tab Bar-Controller erhalten. Hier wird der ausgewählte Controller ist unsere treuen Nav-Controller (# 7), aber dieses Mal seines visibleViewController und topViewController ist SET TO NIL

Wenn wir von hier aus weiter, eine geheimnisvolle Nachricht erscheint in der Debugger-Konsole:

  

Mit zweistufigen Dreh Animation. Zu   verwenden, um die glattere einstufig   Animation, diese Anwendung muss   zweistufigen Verfahren entfernen   Implementierungen.

Mysterious weil Ich bin nicht mit zweistufigen Dreh Animation ! Keine SecondHalf Verfahrensvarianten sind im Spiel überall in meinem Quellcode.

Ach, mein Dreh-aware VC wird nie gesagt, dass die Drehung auftritt (obwohl Drehung auf dem Bildschirm auftritt), so natürlich meine Sicht ist alles als Ergebnis verschmutzt werden. Chaos und Trauer ergeben. : (

Wir werden nicht einmal die Mühe, den Stack an dieser Stelle knallen.

Ich denke, die View-Controller-doc Hinweise auf das mögliche Problem:

  

Wenn Sie benutzerdefinierte ausführen   Animationen während einer Ausrichtung   ändern, so können Sie dies in einem von zwei   Wegen. Orientierungsänderungen genutzt   auftreten, in zwei Schritten, mit Benachrichtigungen   auftretende am Anfang, in der Mitte,   und Endpunkte der Rotation.   Doch in iPhone OS 3.0, Unterstützung war   hinzugefügt zur Orientierung Durchführung   Änderungen in einem Schritt. Verwendung eines Ein-Schritt   Orientierungsänderung neigt, schneller zu sein   als der ältere zweistufigen Prozess und ist   im Allgemeinen für jeden neuen empfohlen   Code.

Ich frage mich, ob MoreNavigationController reagiert noch auf den zweistufigen Prozess, und somit alle Versuche stolpern die Ein-Schritt-Verfahren zu benutzen? Beachten Sie, dass, wenn Sie zu den zweistufigen Meldungen reagieren, die Ein-Schritt-Variante (auch hier pro Docs) nicht funktionieren. Ich bin nicht auf sie reagiert, aber ich habe den leisen Verdacht, etwas hinter den Kulissen.

In der Tat, wenn ich das einstufige Verfahren kommentieren Sie, und versuchen Sie auf willAnimateSecondHalfOfRotationFromInterfaceOrientation zu reagieren: Dauer: , I Sie das Memo erhalten! Aber es ist Pop-off noch nicht den Stapel sehr sauber (in Bezug auf Grafik). Noch seltsamer: willAnimateFirstHalfOfRotationFromInterfaceOrientation: Dauer: wird nicht aufgerufen, auch wenn ich versucht, einen Anruf zu sich selbst zu schleichen (mit der FirstHalf Nachricht) in ShouldAutorotateToInterfaceOrientation: . Es kehrt sofort während einer Spur, als ob ich noch nie definiert. Seufz.

Das ist also die Play-by-Play.

Insgesamt hat jemand erfolgreich Einstufen-Gerät Rotation behandelt für eine VC aus einer Tableiste Kontrolleurs MoreNavigationController aufgerufen? Neugierige wollen wissen!

War es hilfreich?

Lösung

Apple-abrät Subklassifizieren UITabBarController, so fand ich eine einfache Möglichkeit, anstelle der Autorotation mit Kategorien zu behandeln. Es ist fix nicht Ihren Fehler mit dem Mehr ... View-Controller, aber ich denke, es ist eine Apple-freundliche Art und Weise der Arbeit erledigt zu bekommen (und bedeutet weniger Subklassifizieren für Sie).

Um alle Register in meiner Anwendung autorotate richtig zu machen, ich habe -shouldAutorotateToInterfaceOrientation definiert: in meinen benutzerdefinierten Ansicht-Controller, aber sie sind alle innerhalb UINavigationControllers innerhalb eines UITabBarController, so wird die Nachricht nicht, die Kette zu meinem VC herabgesandt bekommen bis diese beiden reagieren auch. So habe ich die folgenden Zeilen zu meiner AppDelegate Datei:

  

Zu der Unterseite MyAppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end
  

Zu der Unterseite MyAppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

Andere Tipps

Es scheint, wir haben einen Fehler. Ich habe ein reproduzierbares, minimales Testfall erstellt und berichtet es über Apple-Bug Reporter ( RADAR Problem 7.139.857 ) .

Update:. Dies wird als von iPhone OS 3.1 behoben worden

Das wesentliche Problem ist:

  

View-Controller bereits auf einem   Navigation Controller-Stack nicht   erhalten    willAnimateRotationToInterfaceOrientation: Dauer:   Nachrichten, wenn ein Tab Bar Kontrolleurs   'Mehr Navigation Controller' ist in   verwenden.

Dieses Problem macht nicht auftreten, wenn der Tableiste Artikel Ansicht-Controller Grund View-Controller sind. Nur wenn sie die Navigation-Controller sind und nur , wenn die „Mehr“ Navigationshierarchie im Einsatz ist.

Die Konsolenmeldung (in Bezug auf zweistufigen Dreh Animation) schlägt vor, dass der Rahmen etwas in (der Mehr Navigation Controller?) Noch einen zweistufigen Animation mit, obwohl einstufig jetzt ab iPhone OS 3.0 wird empfohlen.

Das könnte erklären, warum willAnimateRotationToInterfaceOrientation: ist nicht in diesem besonderen Fall genannt. Per-View-Controler Dokumentation von Apple, wird diese Nachricht nicht aufgerufen werden, wenn zweistufigen, erste / zweite Halb Orientierung Nachrichten reagiert werden, die statt.

Eine leicht modifizierte Version von victorb Antwort , die jeden einzelnen View-Controller ermöglicht zu entscheiden, ob er eine Drehung ermöglicht.

hier als Kern für eine einfacheres Kopieren & Forking

AppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end

AppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *selectedVC = [self selectedViewController];
    if ([selectedVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [selectedVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *visibleVC = [self visibleViewController];
    if ([visibleVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [visibleVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top