So erzwingen Sie, dass ein UIViewController in iOS 6 eine Hochformatausrichtung erhält

85

Da die ShouldAutorotateToInterfaceOrientationin iOS ist veraltet 6 und verwenden ich , dass eine bestimmte Ansicht zu zwingen Porträt nur , was ist der richtige Weg , dies in iOS 6 zu tun? Dies ist nur für einen Bereich meiner App, alle anderen Ansichten können gedreht werden.

Neal
quelle

Antworten:

117

Wenn Sie möchten, dass alle unsere Navigations-Controller den Draufsicht-Controller respektieren, können Sie eine Kategorie verwenden, damit Sie nicht eine Reihe von Klassennamen ändern müssen.

@implementation UINavigationController (Rotation_IOS6)

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

Wie einige Kommentare zeigen, ist dies eine schnelle Lösung für das Problem. Eine bessere Lösung ist der UINavigationController der Unterklasse, in dem diese Methoden abgelegt werden. Eine Unterklasse hilft auch bei der Unterstützung von 6 und 7.

Anthony
quelle
3
Ich kann bestätigen, dass dies funktioniert. Sie können auch "[self.viewControllers lastObject]" durch "self.topViewController" ersetzen, wenn Sie möchten.
Wayne Liu
3
Wenn Sie UITabBarController verwenden, ist diese UINavigationController-Kategorie keine Hilfe. Sie sollten stattdessen Kategorie auf UITabBarController machen ...
Borut Tomazin
46
Das Problem mit dieser Lösung ist, dass es nicht funktioniert, wenn Sie einen Pop-Controller im Querformat verwenden und Ihr neuer Top-Controller nur Hochformat unterstützt (oder umgekehrt). Diese Rückrufe werden in diesem Fall nicht aufgerufen, und ich muss noch herausfinden, wie neuen oberen Controller in die richtige Ausrichtung bringen. Irgendwelche Ideen?
Lope
4
Ich habe UINavigationController unterklassifiziert und als window.rootController festgelegt. Ich habe alle 3 Methoden implementiert. Es funktioniert hervorragend, wenn Sie die Drehung des Geräts ändern. Das Problem ist, dass diese Methoden (und nichts im Zusammenhang mit der Drehung) aufgerufen werden, wenn Sie den Pop-View-Controller
öffnen
4
Wenn ich Push oder Pop vom Querformat-View-Controller aus mache, ändert sich dieser erzwungene UIViewController in Querformat. Wenn ich mich jedoch in Hochformat drehe, funktioniert es einwandfrei und es wird sich nie in Querformat verwandeln. Das einzige Problem beim Push oder Pop aus der Landschaft. Bitte helfen Sie
Tariq
63

Der beste Weg für iOS6 wird speziell in "iOS6 By Tutorials" vom Ray Wenderlich-Team - http://www.raywenderlich.com/ - angegeben und ist in den UINavigationControllermeisten Fällen besser als Unterklassen .

Ich verwende iOS6 mit einem Storyboard, das einen UINavigationControllerSatz als anfänglichen Ansichts-Controller enthält.

//AppDelegate.m - Diese Methode ist vor iOS6 leider nicht verfügbar

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m - Gibt die Orientierungen zurück, die Sie für jede unterstützen möchten UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}
Phil
quelle
1
Dies ist die beste Lösung für iOS 6
Homam
2
@Phil, es funktioniert gut für iOS 6. Aber in einigen Fällen, wenn Sie von Querformat zu Hochformat wechseln, funktioniert es nicht. Irgendeine Idee warum es passiert?
Kirti Nikam
1
Sehr nützliche Lösung. Für mich das Beste.
Oscar Castellon
1
Arbeiten mit iOS 7 Beta 6. Funktioniert in meinem Fall beim Übergang von Querformat zu Hochformat.
Martin Berger
Ich bin in iOS 6, aber das funktioniert nicht. Es wird in der Zeile "UIViewController * presentViewController" unterbrochen.
Marcel Marino
39

Diese Antwort bezieht sich auf die Fragen, die in den Kommentaren des OP-Beitrags gestellt wurden:

Um zu erzwingen, dass eine Ansicht in einer bestimmten Ausrichtung angezeigt wird, fügen Sie Folgendes in viewWillAppear ein:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
    UIViewController *c = [[UIViewController alloc]init];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

Es ist ein bisschen wie ein Hack, aber dies erzwingt die UIViewControllerDarstellung im Hochformat, selbst wenn der vorherige Controller Querformat war

UPDATE für iOS7

Die oben genannten Methoden sind jetzt veraltet. Verwenden Sie daher für iOS 7 Folgendes:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
     UIViewController *c = [[UIViewController alloc]init];
     [c.view setBackgroundColor:[UIColor redColor]];
     [self.navigationController presentViewController:c animated:NO completion:^{
            [self.navigationController dismissViewControllerAnimated:YES completion:^{
            }];
     }];
}

Interessanterweise muss zum Zeitpunkt des Schreibens entweder die Gegenwart oder die Entlassung animiert sein. Wenn beides nicht der Fall ist, erhalten Sie einen weißen Bildschirm. Keine Ahnung, warum das funktioniert, aber es funktioniert! Der visuelle Effekt ist je nach Animation unterschiedlich.

Craig Watkinson
quelle
Danke, ich werde es versuchen, wenn ich ein paar Minuten Freizeit finde
Lope
@RohanAgarwal es funktioniert wie angekündigt, ich benutze es hier. Sie müssen jedoch auch den Code der akzeptierten Antwort implementieren, sonst funktioniert er nicht.
Dennis Munsie
2
Hat jemand herausgefunden, wie dies mit der richtigen Rotationsanimation gleichzeitig funktioniert? Es ist ein wenig irritierend zu sehen, wie es ohne Animation von Hochformat zu Querformat wechselt. Es funktioniert, nur in der Hoffnung, dass es ein bisschen besser funktioniert.
Dennis Munsie
@Craig Watkinson Es funktioniert nicht im Storyboard. und presentModalViewController und entlassenModalViewControllerAnimated ist veraltet, wenn ich presentVirecontroller verwende, dann funktioniert es nicht. Bitte helfen Sie mir
Kalpesh
1
Für ios8 stürzt descViewControllerAnimated nur ab. Ich habe festgestellt, dass der Aufruf von [NWSAppDelegate sharedInstance] .window.rootViewController = nil; [NWSAppDelegate sharedInstance] .window.rootViewController = previousRootController funktioniert gut.
Alexey
36

Daher stieß ich auf das gleiche Problem, wenn nur modale Hochformatansichten angezeigt wurden. Normalerweise würde ich eine erstellen UINavigationController, die viewControllerals festlegen rootViewControllerund dann die UINavigationControllerals modale Ansicht anzeigen. Bei iOS 6 viewControllerwird der Navigationscontroller nun nach den unterstützten Schnittstellenausrichtungen gefragt (die jetzt standardmäßig nur für das iPad und für das iPhone alles andere als verkehrt herum sind).

Lösung : Ich musste UINavigationControllerdie Autorotationsmethoden unterordnen und überschreiben. Irgendwie lahm.

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
felsig
quelle
1
funktioniert bei mir nicht Ich hatte diesen Code mit global auf alle Ausrichtungen eingestellt
phil88530
2
unterstütztInterfaceOrientations sollte eine NSUInteger zurückgeben, nicht BOOL. Siehe developer.apple.com/library/ios/#featuredarticles/…
tomwhipple
Es hat funktioniert, für mich ist es der Tabbarcontroller. Nochmals vielen Dank für die Antwort
otakuProgrammer
FWIW, ich musste auch diesen Weg gehen ... Sonst hat nichts funktioniert. Vielen Dank.
Steve N
15

IOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

IOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{

    //    UIInterfaceOrientationMaskLandscape;
    //    24
    //
    //    UIInterfaceOrientationMaskLandscapeLeft;
    //    16
    //
    //    UIInterfaceOrientationMaskLandscapeRight;
    //    8
    //
    //    UIInterfaceOrientationMaskPortrait;
    //    2

    //    return UIInterfaceOrientationMaskPortrait; 
    //    or
          return 2;
}
Roshan Jalgaonkar
quelle
Ausgezeichnet! Muss maximal oben in diesem Thread sein. Weil es der einfachste Weg ist, ein Problem zu lösen
Alex
@Roshan Jalgaonkar In ios 6 Es funktioniert nicht für mich Ich brauche nur Porträt mit Down-Home-Taste, wie kann ich diese UIOrientation einstellen ....
Karthik
@Karthik Sie müssen unterstützte Rotationen im Ziel Ihrer App aktivieren, damit dies funktioniert.
Alejandro Iván
@ AlejandroIván k thnx
Karthik
10

Ich bin mit der Antwort von @aprato nicht einverstanden, da die UIViewController-Rotationsmethoden in Kategorien selbst deklariert sind, was zu undefiniertem Verhalten führt, wenn Sie dann in einer anderen Kategorie überschreiben. Es ist sicherer, sie in einer UINavigationController- (oder UITabBarController-) Unterklasse zu überschreiben

Dies gilt auch nicht für das Szenario, in dem Sie aus einer Querformatansicht nur VC in ein Hochformat verschieben / präsentieren / einfügen oder umgekehrt. Um dieses schwierige Problem zu lösen (das von Apple nie angesprochen wurde), sollten Sie:

In iOS <= 4 und iOS> = 6:

UIViewController *vc = [[UIViewController alloc]init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[vc release];

In iOS 5:

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];

Diese werden UIKit WIRKLICH dazu zwingen, alle Ihre SollteAutorotate, unterstütztenInterfaceOrientations usw. neu zu bewerten.

Rafael Nobre
quelle
2
Der erste dieser Abstürze ist für mich unabhängig von der iOS-Version. Sagt Entlassung sollte nicht vor dem Ende der Gegenwart angerufen werden.
Arsenius
@arsenius Kannst du einen Ausschnitt davon posten, wie du es benutzt? Solange es nicht animiert ist, sollte es nicht das von Ihnen erwähnte Problem haben
Rafael Nobre
Ich habe auch das zweite Snippet in viewDidAppear eingefügt und es hilft meiner Situation unter iOS 6 nicht weiter. Die Frage ist hier: stackoverflow.com/questions/15654339/…
arsenius
Entschuldigung, ein letzter Kommentar hier. Wenn Sie den iOS 5-Code nach viewDidAppear verschieben, wird mit dieser Ausgabe eine Art Endlosschleife erstellt: - Überlauf [UIApplication beginIgnoringInteractionEvents]. Ignorieren.
Arsenius
3

Ich habe einen sehr guten Ansatz beim Mischen von https://stackoverflow.com/a/13982508/2516436 und https://stackoverflow.com/a/17578272/2516436

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;


    if(self.window.rootViewController){
        UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
        orientations = [presentedViewController supportedInterfaceOrientations];
    }

    return orientations;
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

und geben Sie die Orientierungen zurück, die Sie für jeden UIViewController unterstützen möchten

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}
Alex Guerra
quelle
1

Ich habe eine relativ komplexe universelle App mit UISplitViewController und UISegmentedController und habe einige Ansichten, die in Querformat mit dargestellt werden müssen presentViewController. Mit den oben vorgeschlagenen Methoden konnte ich das iPhone ios 5 & 6 akzeptabel zum Laufen bringen, aber aus irgendeinem Grund weigerte sich das iPad einfach, es als Landschaft darzustellen. Schließlich fand ich eine einfache Lösung (implementiert nach stundenlangem Lesen und Ausprobieren), die sowohl für Geräte als auch für iOS 5 und 6 funktioniert.

Schritt 1) ​​Geben Sie auf dem Controller die erforderliche Ausrichtung an (mehr oder weniger wie oben angegeben).

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    NSInteger mask = UIInterfaceOrientationMaskLandscape;
    return mask;

}

Schritt 2) Erstellen Sie eine einfache UINavigationController-Unterklasse und implementieren Sie die folgenden Methoden

-(BOOL)shouldAutorotate {
        return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskLandscape;
}

Schritt 3) Präsentieren Sie Ihren viewController

vc = [[MyViewController alloc]init];
MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc];
[self myNavigationController animated:YES completion:nil];

Hoffe das ist hilfreich für jemanden.

user216661
quelle
1

Hier nicht langweilig zu sein, aber würden Sie so freundlich sein, Ihre Unterklasse zu teilen? Danke dir.

edit: nun, ich habe es endlich geschafft, die Unterklasse war kinderleicht zu machen. Ich musste nur die navigationControllerin der AppDelegateals UINavigationControllerSubclassanstelle der Standardeinstellung deklarieren UINavigationControllerund dann Ihre Unterklasse ändern mit:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

So kann ich jede Ansicht einstellen, die ich drehen möchte oder nicht, indem ich anrufe viewDidLoad

_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

Hoffe, diese Optimierung wird auch anderen helfen, danke für deinen Tipp!

Tipp: Nutzen Sie

- (NSUInteger)supportedInterfaceOrientations

Sie haben also nicht die gewünschte Hochformatansicht im Querformat oder umgekehrt.

Roland
quelle
0

Ich habe es nicht selbst getestet, aber die Dokumentation besagt, dass Sie diese Methoden jetzt überschreiben können: supportedInterfaceOrientationsund preferredInterfaceOrientationForPresentation.

Sie können wahrscheinlich das erreichen, was Sie wollen, indem Sie nur die gewünschte Ausrichtung für diese Methoden festlegen.

J_D
quelle
0

Die Antworten unter Verwendung von Unterklassen oder Kategorien, um VCs in den Klassen UINavigationController und UITabBarController zuzulassen, funktionieren gut. Das Starten eines Nur-Hochformat-Modals von einem Querformat-Controller in der Registerkartenleiste ist fehlgeschlagen. Wenn Sie dies tun müssen, verwenden Sie den Trick, eine nicht animierte modale Ansicht anzuzeigen und auszublenden , aber tun Sie dies in der viewDidAppear-Methode . In viewDidLoad oder viewWillAppear hat es bei mir nicht funktioniert.

Abgesehen davon funktionieren die oben genannten Lösungen einwandfrei.

Peter
quelle
0

Für Monotouch können Sie dies folgendermaßen tun:

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
    {
    return UIInterfaceOrientationMask.LandscapeRight;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
    {
    return UIInterfaceOrientation.LandscapeRight;
}
TJS
quelle
-1

Gehen Sie einfach zu project.plist, fügen Sie die Ausrichtung der unterstützten Benutzeroberfläche hinzu und fügen Sie dann nur Portrait (untere Home-Schaltfläche) und Portrait (obere Home-Schaltfläche) hinzu.

Sie können diese Ausrichtung gemäß Ihren Projektanforderungen hinzufügen oder entfernen.

Vielen Dank

Muhammad Saad Ansari
quelle
1
Es geht um einen bestimmten View Controller, nicht für die gesamte Anwendung.
Muhammad Rizwan
-2

1) Überprüfen Sie Ihre Projekteinstellungen und info.plist und stellen Sie sicher, dass nur die gewünschten Ausrichtungen ausgewählt sind.

2) Fügen Sie Ihrem obersten Ansichts-Controller (Navigations-Controller / Tabbar-Controller) die folgenden Methoden hinzu.

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3) Fügen Sie Ihrem App-Delegaten die folgenden Methoden hinzu

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait;

}
ehanna
quelle
-3

Fügen Sie dies in die .m-Datei von jedem ein, den ViewControllerSie nicht drehen möchten:

- (NSUInteger)supportedInterfaceOrientations
{
    //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
    return UIInterfaceOrientationMaskPortrait;
}

Sehen Sie hier für weitere Informationen.

Navy Gunner
quelle