Search code examples
iosobjective-cuiviewcontrolleruinavigationcontrollerautorotate

Issue in autorotating UIViecontrollers in UINavigationcontroller


I'd downloaded a sample from this tutorial site about rotating the viewcontrollers in navingation controllers.

That sample project functionality

  • Support potrait for FirstviewController
  • Support all orientations for second view controller(pushed from first VC)

What I need is,

  • FirstviewController should support all orientations
  • Second view controller(pushed from first VC) should support potrait alone.

What I did was, just swapped the codes in the view controllers

In first view controller

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}
- (BOOL)shouldAutorotate  
{
    return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation 
{
    return UIInterfaceOrientationPortrait;
}

In Second view controller and

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)shouldAutorotate
{
    return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

But, both the view controllers are rotating.

How can I fix this issue? Any suggestions, please share.

----EDIT----

If I rotate the simulator to landscape before pushing, second VC is also in landscape view.

If I push to second vc in potrait, the second VC is in potrait mode(it's not rotating if I rotate there.)

I put log in customNavigationcontroller NSLog(@"self.topViewController.class %@",self.topViewController.class);. It's only logging for firstview controller after pushing to second vc it's not logging


Solution

  • I suggest an easier way to solve this issue.

    Select your project's target and configure it like this:

    Select your target and set this

    Then go to Appdelegate.m and paste:

    - (UIViewController*)topViewController {
    return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
    }
    
    - (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    // Handling UITabBarController
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    }
    // Handling UINavigationController
    else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    }
    // Handling Modal views
    else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    }
    // Handling UIViewController's added as subviews to some other views.
    else 
    {
        for (UIView *view in [rootViewController.view subviews])
        {
            id subViewController = [view nextResponder];    // Key property which most of us are unaware of / rarely use.
            if ( subViewController && [subViewController isKindOfClass:[UIViewController class]])
            {
                return [self topViewControllerWithRootViewController:subViewController];
            }
        }
        return rootViewController;
        }
    }
    

    Now here's the fun part.

    Put this method on AppDelegate.m,you can decide the orientation of every controller here.

    - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    
    id presentedViewController = [self topViewController];
    NSString *className = presentedViewController ? NSStringFromClass([presentedViewController class]) : nil;
    
    if (window && [className isEqualToString:@"FirstViewController"]) { //FirstviewController should support all orientations
        return UIInterfaceOrientationMaskAll;
    } else {
        return UIInterfaceOrientationMaskPortrait; //Second view controller(pushed from first VC) should support potrait alone.
    }
    }
    

    You can then remove all the other methods you've added such as shouldAutorotateToInterfaceOrientation, shouldAutorotate , supportedInterfaceOrientations , preferredInterfaceOrientationForPresentation. All these methods are now all unnecessary.

    -----Edit-----

    Simply using

     [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIInterfaceOrientationPortrait] forKey:@"orientation"];
    

    in all view controllers where I need potrait will do the trick. no other things needed.