2
votes

I can see that this is something that has been troubling a lot of people:/

I have a UITabBarController that has 4 viewControllers, all of type UINavigationController. One of the navigationControllers gets a viewController pushed onto its stack, this viewController should be presented in landscape mode/orientation.

The viewController is a graph, it is the absolutely only place in the app where landscape makes sense. (I hide the UITabBar when this is presented to not lead the user to believe this will work everywhere)

To make a UITabBarController respond correctly to changes in orientation all its viewControllers need to return the same value from the delegate method:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

So to accomodate this behavior I have implemented this method in all the viewControllers belonging to the UITabBarController:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    BOOL canRotate = [defaults boolForKey:@"can_rotate"];

    return canRotate;
}

The "trick" is now that when my can-be-landscape viewController is pushed I do this:

- (void) viewWillAppear:(BOOL)animated {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setBool:YES forKey:@"can_rotate"];
    [defaults synchronize];

}

and when it is popped, I do this:

- (void) viewWillDisappear:(BOOL)animated {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setBool:NO forKey:@"can_rotate"];
    [defaults synchronize];

}

This works really well. When the viewController is on the stack I can rotate the device and the view follows.

The problem is however, that if the user taps the "back" button on the navigationBar while in landscape mode, thus popping the viewController to the previous viewController, this "old" viewController is of course also in landscape mode. To make things worse, because I set the BOOL to NO, this "old" viewController can not rotate back when I orientate the device to portrait mode.

Is there a way to update everything so that none of my other viewControllers will be in landscape mode when I pop the can-be-in-landscape mode viewController?

I am a bit worried that if this could be done from landscape to portrait it should also be possible from portrait to landscape, thus making my "hack" unnecessary.. but if it can not, then I am back to square one :/

Hope I am close and that someone could help me get there, thanks:)

1

1 Answers

1
votes

I think I can simplify the whole thing....

- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
return NO;
}

-(void) viewDidAppear:(BOOL)animated { [UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:0.5f]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

    self.view.transform = CGAffineTransformIdentity;
    self.view.transform = CGAffineTransformMakeRotation(90.0*0.0174532925);
    self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
    self.view.center = CGPointMake(160.0f, 240.0f);

// [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight;

[UIView commitAnimations];
[super viewDidAppear:animated];

}

Nothing auto rotates, but you then manually rotate the view you want moved. If you don't need keyboard support in the view you don't need to change the statusBarOrientation.

If you don't always want that view rotated then you have a slightly harder issue - you might want to check the accelerometer values to figure out which way round the phone is (or it might be possible to imply which way the phone has been turned by calls to shouldAutotateToInterfaceOrientation and then just call the transform code as and when you need to.