navigationController pushed ViewControllers won

2019-07-24 15:35发布

I'm having difficulty getting a navigation controller to autorotate correctly. The display will autorotate on the initial view (root view controller), but it will not rotate on any new views that are pushed on. It keeps the view orientation that the initial view had when pushed.

In my App Delegate I have a navigation controller and push it's view.

[window addSubview:navigationController.view];
[window makeKeyAndVisible];

In the root view controller I allow all orientations and I push other views onto the controller's stack.

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

ParkingListController *parklc = [[ParkingListController alloc] autorelease];
[[self navigationController] pushViewController:parklc animated:YES];

I see "Yes, we should!" logged once when the new view loads, but it does not fire when the device is actually rotated.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    NSLog(@"Yes, we should!");
    return YES;
}

I do not have any init overrides and the info.plist lists all four orientations.

What am I missing? Thanks!

EDIT 2011-07-07:

Strangely the map view that is pushed on when you select an item from the table view does autorotate! Why can it rotate when the table view it came from cannot?

4条回答
Deceive 欺骗
2楼-- · 2019-07-24 15:36

I would suggest two things:

  1. ensure that all of your UIViewControllers' shouldAutorotateToInterfaceOrientation return YES;

  2. put the log message in willRotateToInterfaceOrientation to verify that the views react to device rotation; shouldAutorotateToInterfaceOrientation is a method that can be called in unpredictable ways by the framework (i.e, it is not always called when autorotating).

Apart from that, it should work.

查看更多
We Are One
3楼-- · 2019-07-24 15:50

Have you ensured that shouldAutorotateToInterfaceOrientation of the ParkingListController also returns YES?

查看更多
在下西门庆
4楼-- · 2019-07-24 15:53

You are using a UINavigationController and it should return true for rotation. Please extend UINavigationController and use the extended class in Interface builder.

#import <Foundation/Foundation.h>
@interface IRUINavigationController : UINavigationController {
}
@end

#import "IRUINavigationController.h"
@implementation IRUINavigationController
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    [self.visibleViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
} 
@end

I have used this is many projects and it works.

查看更多
看我几分像从前
5楼-- · 2019-07-24 16:01

Every view controller pushed onto the navigation controllers stack have to support the same orientations. This means that it is not possible to have some view controllers only supporting portrait and others only supporting landscape. In other words all view controllers on the same navigation controller stack should return the same in the delegate:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

But there is a simple solution to this! Here is an example for going from portrait to landscape. Here is the steps to do it and below is code to support it.

  1. Create a ‘fake’ view controller that will be root in a sub navigation controller. This view controller should support landscape.
  2. Create a new instance of a UINavigationController, add an instance of the ‘fake’ view controller as root and an instance of your landscape view controller as second view controller
  3. Present the UINavigationController instance as modal from the parent view controller

First, create a new view controller (FakeRootViewController) with this code:

@interface FakeRootViewController : UIViewController
@property (strong, nonatomic) UINavigationController* parentNavigationController;
@end

@implementation FaceRootViewController
@synthesize parentNavigationController;
// viewWillAppear is called when we touch the back button on the navigation bar
(void)viewWillAppear:(BOOL)animated {
  // Remove our self from modal view though the parent view controller
  [parentNavigationController dismissModalViewControllerAnimated:YES];
}
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
   return (interfaceOrientation == UIInterfaceOrientationIsLandscape(interfaceOrientation));
} 

Here is the code to present the view controller that you wish to show in landscape mode:

FakeRootViewController* fakeRootViewController = [[FakeRootViewController alloc] init];[fakeRootViewController.navigationItem setBackBarButtonItem:backButton]; // Set back button
// The parent navigation controller is the one containing the view controllers in portrait mode.
fakeRootViewController.parentNavigationController = parentNavigationController;

UINavigationController* subNavigationController = // Initialize this the same way you have initialized your parent navigation controller.

UIViewController* landscapeViewController = // Initialize the landscape view controller

[subNavigationController setViewControllers:
   [NSArray arrayWithObjects:fakeRootViewController, 
                                               landscapeViewController, nil] animated:NO];

[_navigationController presentModalViewController:subNavigationController animated:YES];

Remember that the landscapeViewController should also have this implementation:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
   return (interfaceOrientation == UIInterfaceOrientationIsLandscape(interfaceOrientation));
} 
查看更多
登录 后发表回答