wake-up-neo.com

Wie kann die Ausrichtung des Präsentationscontrollers beibehalten werden, wenn der modale Viewcontroller deaktiviert wird?

Ich habe diese App, an der ich gerade arbeite, und ich brauche ALLE meine View-Controller, aber einer, um im Portrait zu sein. Der einzige View-Controller, der speziell ist, brauche ich, um in jede Orientierung des Telefons drehen zu können.

Dazu präsentiere ich es modal (nicht eingebettet in einen NavigationController)

So (zum Beispiel) ist meine Struktur so:

  • fenster - Portrait
    • root View Controller (UINavigationController - Portrait)
      • home View Controller (UIViewController - Portrait)
        • detailansicht Controller (UIViewController - Portrait)
        • .
        • .
        • modal View Controller (UIVIewController - All)

Wenn ich nun meinen modalen View-Controller in einer Querformatposition entlasse, wird mein übergeordneter View-Controller ALSO gedreht, obwohl er diese Ausrichtung nicht unterstützt.

Alle UIViewControllers und UINavigaionControllers in der App erben von denselben allgemeinen Klassen, in denen diese Methoden implementiert sind:

override func supportedInterfaceOrientations() -> Int
{
    return Int(UIInterfaceOrientationMask.Portrait.toRaw())
}

Mein modaler View-Controller überschreibt diese Methode noch einmal und es sieht so aus:

override func supportedInterfaceOrientations() -> Int
{
    return Int(UIInterfaceOrientationMask.All.toRaw())
}

Update 1

Es scheint, dass dies nur unter iOS8 Beta geschieht. Weiß jemand, ob sich etwas bezüglich der Rotation des View Controllers geändert hat, oder ist dies nur ein Fehler in der Beta?

32
Mihai Fratu
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([self.window.rootViewController.presentedViewController isKindOfClass: [SecondViewController class]])
{
    SecondViewController *secondController = (SecondViewController *) self.window.rootViewController.presentedViewController;

    if (secondController.isPresented)
        return UIInterfaceOrientationMaskAll;
    else return UIInterfaceOrientationMaskPortrait;
}
else return UIInterfaceOrientationMaskPortrait;
}

Und für Swift

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int {

    if self.window?.rootViewController?.presentedViewController? is SecondViewController {

        let secondController = self.window!.rootViewController.presentedViewController as SecondViewController

        if secondController.isPresented {
            return Int(UIInterfaceOrientationMask.All.toRaw());
        } else {
            return Int(UIInterfaceOrientationMask.Portrait.toRaw());
        }
    } else {
        return Int(UIInterfaceOrientationMask.Portrait.toRaw());
    }

}

Für weitere Details überprüfen Sie diesen link

18
ZaEeM ZaFaR

Ich habe das gleiche Problem mit einer App und nach Tagen des Experimentierens habe ich eine Lösung gefunden, die nicht sehr schön ist, aber jetzt funktioniert. Ich verwende die Delegate-Methode application:supportedInterfaceOrientationsForWindow: innerhalb des appdelegate. 

Ich habe ein Testprojekt erstellt und es hier auf Github (einschließlich einer GIF, die das Ergebnis anzeigt ...)

// Anmerkung: es ist nicht in Swift, aber ich hoffe, es hilft trotzdem

7
jules

Nach langem Experimentieren bin ich überzeugt, dass dies ein "Feature" von iOS 8 ist.

Wenn Sie darüber nachdenken, ist das absolut sinnvoll, denn es kommt schon lange her.

  • In iOS 4 war es beispielsweise möglich, die App-Rotation zu erzwingen, wenn der Ansichts-Controller in einem Registerkarten-Controller und einem Navigations-Controller geändert wurde, und wenn ein Controller angezeigt/abgebrochen wurde.

  • In iOS 6 war es dann unmöglich, die App-Rotation zu erzwingen, außer wenn ein View-Controller angezeigt/abgebrochen wurde (wie ich bereits in vielen Antworten erläutert habe, z. B. hier ).

  • Nun, unter iOS 8, vermute ich, dass es unmöglich ist, die App-Rotation überhaupt zu erzwingen (außer beim Start). Es kann bevorzugen eine bestimmte Ausrichtung sein, so dass es, sobald es sich in dieser Ausrichtung befindet, dort verbleiben wird, aber es kann nicht force die App in diese Ausrichtung gehen.

    Stattdessen wird erwartet, dass sich Ihr View Controller "anpasst". Es gibt mehrere Videos der WWDC 2014, die sich auf "Anpassung" konzentrieren, und jetzt beginne ich zu verstehen, dass dies ein Grund ist, warum dies so wichtig ist.

    EDIT: In Seed 4 sieht es so aus, als käme diese Funktion (Rotation bei Präsentation und Entlassung) zurück!

4
matt

Wir haben eine App implementiert, die über einen Landschaftscontroller verfügt, der einen View-Only-View-Controller darstellt. Wurde von Apple auf iOS 8 überprüft. Wir überschreiben nur unterstützte InterfaceOrientations.

Es ist erwähnenswert, dass wir viele Unterschiede zwischen den Betas 3,4 und 5 gefunden haben. Am Ende mussten wir auf das GM warten, bevor wir uns bemühten, unsere App für iOS 8 zu aktualisieren.

Sie müssen unter iOS 8 sehr vorsichtig sein, um sicherzustellen, dass Sie Folgendes nicht tun:

[self dismissViewControllerAnimated:YES completion:nil]
[self presentViewController:vc animated:YES completion:nil]

Wenn es sich bei dem ausgehenden Vc um ein Hochformat und bei dem ankommenden um ein Querformat handelt, können einige Ansichtsrahmen sehr durcheinander geraten. Präsentieren Sie stattdessen das eingehende vc im Beendigungsblock des Abbruchaufrufs.

[self dismissViewControllerAnimated:YES completion:^{
    [self presentViewController:vc animated:YES completion:nil]
}];
3
Airsource Ltd

Dies ist eigentlich einfacher und kann ohne zusätzliche Eigenschaften ausgeführt werden (hier ein Beispiel mit AVPlayerViewController):

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        if ([self.window.rootViewController.presentedViewController isKindOfClass: [AVPlayerViewController class]])
            return self.window.rootViewController.presentedViewController.isBeingDismissed ? 
            UIInterfaceOrientationMaskPortrait : UIInterfaceOrientationMaskAll;
        else
            return UIInterfaceOrientationMaskPortrait;
    } else {
        return UIInterfaceOrientationMaskAll;
    }
}
2
xfyre

Tolle Frage und eine großartige Antwort von @ZaEeM ZaFaR ! Seine Antwort mit this zu kombinieren, führte mich zu einer großartigeren und allgemeineren Lösung. 

Der Nachteil der ersten Antwort ist, dass Sie die Variable isPresented in jedem View-Controller verwalten müssen, der Rotationen zulässt. Außerdem müssen Sie die Überprüfung erweitern und in supportedInterfaceOrientationsForWindow für jeden virtuellen Computer, der eine Drehung zulässt, einen Cast erstellen. 

Der Nachteil der zweiten Antwort ist, dass sie nicht funktioniert. Es dreht sich auch das präsentierte Vc, wenn das präsentierte Vc entlassen wird. 

Diese Lösung erlaubt Rotation in allen VCs, in denen Sie canRotate () {} ablegen können, und dreht das präsentierende VC nicht.

Swift 3:
In AppDelegate.Swift:

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) {
        if (rootViewController.responds(to: Selector(("canRotate")))) {
            // Unlock landscape view orientations for this view controller if it is not currently being dismissed
            if !rootViewController.isBeingDismissed{
                return .allButUpsideDown
            }
        }
    }

    // Only allow portrait (standard behaviour)
    return .portrait
}

private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? {
    if (rootViewController == nil) {
        return nil
    }
    if (rootViewController.isKind(of: UITabBarController.self)) {
        return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
    } else if (rootViewController.isKind(of: UINavigationController.self)) {
        return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
    } else if (rootViewController.presentedViewController != nil) {
        return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
    }
    return rootViewController
}

In jedem Ansichtscontroller, bei dem die Drehung zulässig sein sollte:

func canRotate(){}
1
kuhr

Versuchen Sie im Root-View-Controller Folgendes hinzuzufügen:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

Arbeitete für mich.

1

Swift 3.0 OR oben, Überprüfen Sie einfach die Eigenschaft "isBeingDismissed" des angezeigten Ansichtscontrollers . Nachfolgend finden Sie Beispielcode. Dies bedeutet, dass der Ansichts-Controller unmittelbar nach dem Schließen des angezeigten Ansichts-Controllers in den Hochformat-Modus gedreht wird.

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController)
{
  if rootViewController.canRotateVC == true
  {
    if baseVC.isBeingDismissed == false
    {
      return .allButUpsideDown
    }
  }
}

  return .portrait}

sie können topController mit dem folgenden Code erhalten:

  private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController?{
if (rootViewController == nil) { return nil }if (rootViewController.isKind(of: (UITabBarController).self))
{
  return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
}
else if (rootViewController.isKind(of:(UINavigationController).self))
{
  return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
}
else if (rootViewController.presentedViewController != nil)
{
  return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
}
return rootViewController }
0
Hiren Panchal