问题
A minimal illustrative Xcode project for this is available on github.
On my UIWindow, when I add second (and subsequent) UITableView's as subviews, they do not rotate properly, and thus appear sideways. This is only tested in the Simulator. Here's a little code for you:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
ShellTVC* viewA = [[ShellTVC alloc] initWithTitle:@"View A"];
ShellTVC* viewB = [[ShellTVC alloc] initWithTitle:@"View B"];
// The first subview added will rotate to landscape correctly.
// Any subsequent subview added will not.
// You may try this by various commentings and rearranging of these two statements.
[window addSubview:[viewA tableView]];
[window addSubview:[viewB tableView]];
[window makeKeyAndVisible];
}
viewB appears sideways. Comment out the addSubview for viewB, and viewA appears correctly. Do that for viewA only, and viewB appears correctly.
I am not creating these UITableViewControllers via NIBs, though the UIWindow is.
In case you are wondering, ShellTVC is-a UITableViewController, and implements this method:
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
Also, I have set the UIInterfaceOrientation in the plist file to UIInterfaceOrientationLandscapeLeft.
Probably related -- and unanswered -- SO questions here and here.
回答1:
I think I figured out a way -- possibly the right way -- to do this.
- Create a "master" UIViewController subclass, which implements shouldAutorotate..., and add this as the only view on your window.
- To alternate between viewA or viewB, use the combination of dismissModalViewControllerAnimated: & presentModalViewController:animated: on this master view controller.
Here's some code:
// this doesn't really do much but implement shouldAutorotate...
@interface MasterViewController : UIViewController
@end
@implementation MasterViewController
- (BOOL) shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
@end
@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
MasterViewController* masterVC;
UIViewController* activeTVC;
UIViewController* onDeckTVC;
}
@end
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UIViewController* masterVC = [[MasterViewController alloc] init];
activeTVC = [[ShellTVC alloc] initWithTitle:@"View A"];
onDeckTVC = [[ShellTVC alloc] initWithTitle:@"View B"];
[window addSubview:masterView.view];
[window makeKeyAndVisible];
[masterVC presentModalViewController:activeTVC animated:NO];
}
// you would call this to toggle between "View A" and "View B"
- (void)toggleTVC {
UITableViewController *hold = activeTVC;
activeTVC = onDeckTVC;
onDeckTVC = hold;
[masterVC dismissModalViewControllerAnimated:NO];
[masterVC presentModalViewController:activeTVC animated:NO];
}
Why does this work?
All orientation changes flow through view controllers, not views.
As far as I can tell, the first view or subview that you add to your window gets some special sauce. If that view has a view controller, the window figures it out.
That is, for the first subview only, you can think of this code:
[window addSubview:masterVC.view];
as doing something like this (not a real method!):
[window addSubview:masterVC.view withViewController:masterVC];
I don't understand any more about it than that. I find the fact that I can do this with the first subview, but not others, supremely perplexing. More info welcomed, and please let me know if this helped you or not.
回答2:
Apparently if you add viewB as a child of viewA it will be rotated correctly. This is not a great solution for my project, but it looks like it might be the only workaround.
回答3:
Unfortunately your subviews are only asked about what orientations they support when a change in orientation occurs.
So I end up setting the orientation before I push the new view controller on the stack if I know it's changed:
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
Yes, this is an unsupported call.
回答4:
You can use the UIApplication object to force a particular device orientation.
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
回答5:
Yes, I believe you have to solve this issue by having multiple XIB. I remember seeing this solution through one of books I read in the past. If not, you have play with Translation and position of object in the view... better have separate XIB.
回答6:
This should work.
- (void)viewDidLoad {
if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) ||
([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight))
{
self.view.frame = CGRectMake(0, 0, 1024, 748);
} else {
self.view.frame = CGRectMake(0, 0, 768, 1004);
}
}
来源:https://stackoverflow.com/questions/1632117/iphone-in-landscape-only-after-first-addsubview-uitableviewcontroller-doesnt