UINavigation controller isn't notified about orientation events correctly

75 Views Asked by At

I am working on iOS 6.1 and 7.0. The behavior is the same for both of them. The root view controller is UIVeiwController. It has a property UINavigationViewController which manages all the displayed controllers in my app. I have subclassed UINavigationController and overloaded shouldAutorotate and supportedInterface rotations methods to get correct orientations of each controller pushed in it.

What I want: Push in navigation 3 controllers, the second controller should be only in portrait orientation.

What I get: When I am pushing second controller it is still in landscape mode, despite it's supportedInterfaceOrientation method returns Portrait mode, then push third controller and put simulator or device in landscape mode and pop to my second controller, here is most interesting it goes away from the screen...

My guess Apple documentation says that only most top view controller will be notified about rotations, so when I make navigation controller root it works correct when I make pop from third controller to second but still doesn't work when pushing from first to second. Any way I need to solve this issue with my structure when navigation controller is only a property of root view controller.

Here is a link to project https://github.com/Trubianov/Navigation.git

2

There are 2 best solutions below

1
Ismael On

The problem is that the new workflow makes rotation methods to be checked only once when the controller is presented, that's why it's not working.

When pushing things inside a UINavigationController (or any other UIViewController container) you can decide on the child UIViewController what orientation it supports, and the OS will make it work for you.

My suggestion: unless you have some custom code that you MUST have in your UINavigationController subclass, you should remove it entirely and move the rotation checks to the child view controllers you are presenting

0
Mering On

Here is the solution. If you put UIViewController to window.root, and your navigation controller is just a property of the root controller, than your navigation won't get appropriate callbacks from UIApplication, so u MUST add navigation as child view controller to your root controller.

My code snippet:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    MyNavigationController *navController = [[MyNavigationController alloc] initWithRootViewController:[ViewController1 new]];
    MainViewController *main = [MainViewController new];
    main.myNavigationController = navController;
    [main addChildViewController:navController];
    self.window.rootViewController = main;
    [self.window makeKeyAndVisible];
    return YES;
}

Also is needed to override following methods in MainViewController.

 - (BOOL)shouldAutorotate 
{
   return [self.myNavigationController.topViewController shouldAutorotate]; 
}

- (NSUInteger)supportedInterfaceOrientations 
{
   return [self.myNavigationController.topViewController supportedInterfaceOrientations]; 
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
   return [self.myNavigationController.topViewController            preferredInterfaceOrientationForPresentation]; 
}