0
votes

I have a viewController hierarchy (created in a storyboard) with the following allowed orientations :

+---------------+       +------------------+       +------------------+
+      VC1      +       +        VC2       +       +        VC3       +
+               +   ->  +                  +   ->  +                  +
+ Portrait Only +       + All orientations +       + All orientations +   
+---------------+       +------------------+       +------------------+

In order to have the allowed rotation do work according to the supportedInterfaceOrientations and shouldAutorotate methods of all these ViewControllers, i created a custom UINavigationController subclass, with this simple implementation :

public class SingleOrientationNavigationController: UINavigationController {

    public override func shouldAutorotate() -> Bool {
        if let topVC = topViewController {
            return topVC.shouldAutorotate()
        }
        return false
    }

    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if let topVC = topViewController {
            return topVC.supportedInterfaceOrientations()
        }
        return UIInterfaceOrientationMask.Portrait
    }
}

When the devices rotate, the method shouldAutorotate is called for the navigationController (which is the root controller of my app), which returns the value of the topmost view controller. Everything goes fine when I push VC2 and VC3, which can rotates freely.


Now, I push VC2 (in portrait since VC1 supports only portrait), rotate the screen (since VC2 supports all orientations), and pop to the root view controller. I got the following debug trace :

enter image description here

The supportedInterfaceOrientations method is called for VC1 (in lines 0 and 1), thus the system can know it needs to rotate in order to display properly VC1 : The rotation works fine.

The issue comes when I try to pop from VC3 to VC1 using popToRootViewControllerAnimated, while VC3 is in landscape mode. This case occurs when the connection to the server is lost, so I have to go back to the root view controller. In this case, I cannot get the previous trace since supportedInterfaceOrientations is not called (neither for VC1 nor VC2), and VC1 is displayed in landscape.

How can I pop to VC1 directly from VC3, and have it display in the correct orientation ? I know I can pop from VC3 to VC2 then from VC2 to VC1, but I'd like to go directly from VC3 to VC1, if possible.

1
I don't think it's possible. The only time when I feel i've been able to force rotation is when dismissing modals not even displaying them. I guess if you displayed a navigation controller over VC1 and then when you wanted to go back to VC1 you could just dismiss it and make custom animations to make it seem like it's being pushed from the right or popped from the left. But, if there is a solution that would be great :3A'sa Dickens

1 Answers

0
votes

Im new on Stack and I hope it's not to late to answer the question but I'm in the same situation as the author. Imagine you have a VC4 in Portrait only and if you try to Push it from VC3 (landscape) your VC4 will appear in landscape as well. It looks like the supportedInterfaceOrientations function is not call...

To solve your problem VC3 => VC1 I found a "hack" https://stackoverflow.com/a/15057537/6257992 (I use the IOS 7 method)

I have the same implementation as you.

  1. Create a BlankViewController who overrides the 2 methods defined in the custom NavigationController
  2. Add the code in the link to your ViewWillAppear of VC1 and replace the UIViewController by the Blank one For a "decent" animation :

    • PopToRootViewController = true
    • PresentViewController = false
    • DismissViewController = true

PS: the animation looks better on a phone than in the simulator.

If you find a better way or have any remarks please share.