3

I know this has been asked and discussed a lot here, but I've spent the last few days scouring the internet for different solutions, and no matter what I try - nothing seems to work.

EDIT: Tried this solution as well, still no luck...

I have an iOS7 app (I currently don't care for support for iOS6, but it'll be nice to have) that has a root view controller with a menu that slides from the side (this one, to be specific) and lets you switch between different screens. The selected screen is loaded into a navigation controller, and there's a "modal" type segue between the navigation controller and the screens' view controllers (except for the screen that appears first, which has a relationship with the root view controller). I also tried this with "push" segues, same result. one of these screens has to display only in landscape mode, the others only in portrait.

for this purpose, in my root view controller I've implemented the following:

- (void)awakeFromNib
{
    self.contentViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"contentController"];
    self.menuViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"menuController"];
}

-(NSUInteger)supportedInterfaceOrientations
{
    if (self.contentViewController)
        return [self.contentViewController supportedInterfaceOrientations];

    return UIInterfaceOrientationMaskPortrait;
}

-(BOOL)shouldAutorotate
{
    return YES;
}

In my navigation view controller I have implemented the following:

-(BOOL)shouldAutorotate
{
    return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations];
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

and in each of the portrait screens' view controllers I've implemented:

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

and in the landscape screen:

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationLandscapeLeft;
}

The first screen of the app is a portrait one. So what happens is, the app loads in portrait mode and doesn't rotate to any other orientation (which is great). BUT! Once I load the landscape screen, it loads in portrait mode, and only when I rotate the device to landscape mode, it rotates and locks into landscape mode. And once I switch back to a portrait screen, it loads in landscape mode, and only when I rotate the device to portrait, is rotates and locks into portrait mode, and for some reason makes the screen VERY narrow...

The closest I've ever gotten to a decent solution was implementing this in the landscape screen's view controller:

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
    CGAffineTransform landscapeTransform = CGAffineTransformMakeRotation(degreesToRadian(270));
    landscapeTransform = CGAffineTransformTranslate(landscapeTransform, 0.0, 0.0);
    [self.navigationController.view setTransform:landscapeTransform];
    self.navigationController.view.bounds = CGRectMake(0.0, 0.0, screenRect.size.height, screenRect.size.width);
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
    CGAffineTransform landscapeTransform = CGAffineTransformMakeRotation(degreesToRadian(0));
    landscapeTransform = CGAffineTransformTranslate(landscapeTransform, 0.0, 0.0);
    [self.navigationController.view setTransform:landscapeTransform];
    self.navigationController.view.bounds = CGRectMake(0.0, 0.0, screenRect.size.width, screenRect.size.height);
}
#define degreesToRadian(x) (M_PI * (x)/180.0)

And changing this view controller's supported and preferred orientations to portrait. Which basically makes the whole app lock in portrait mode. Although it looks fine, it seems kinda sketchy and I would much rather have a "clean" solution, and support landscape left AND right. Any ideas on what I'm missing here?

If you need me to provide more code, just tell me. Thanks!! :)

Community
  • 1
  • 1
orenk86
  • 720
  • 9
  • 24

1 Answers1

1

Ok, just in case this interests anyone, this was my solution, using the accepted answer here:

The thing I was missing was in my approach - The landscape VC can't be under the same root VC as the portrait ones, it needs to be or have its own root VC, which is in landscape.

So first, I separated the landscape VC from the rest in the storyboard, now it's completely independent. Next, I created a "view controller switch" method, which basically loads a new controller, sets it to be the root controller, and releases the previous root controller:

+(void)loadController:(UIViewController *)VControllerToLoad andRelease:(UIViewController *)VControllerToRelease
{
    //adjust the frame of the new controller
    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
    CGRect windowFrame = [[UIScreen mainScreen] bounds];
    CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
    VControllerToLoad.view.frame = firstViewFrame;
    //set the new controller as the root controller
    [[[UIApplication sharedApplication].delegate window] setRootViewController:VControllerToLoad];
    //kill the previous view controller
    [VControllerToRelease.view removeFromSuperview];
}

In the landscape VC I added this code:

-(BOOL)shouldAutorotate
{
    return YES;
}

And whenever I need to present the landscape VC or go back the the portrait VCs, I just use the VC switch method. For example:

[AppUtils loadController:landscapeViewController andRelease:portraitNavigationController];

That's it! Now everything works like a charm! :)

Community
  • 1
  • 1
orenk86
  • 720
  • 9
  • 24