IPhone: only in terrain, after the first addSubview, the UITableViewController does not rotate properly

The minimal illustrative Xcode project for this is available on github .

In my UIWindow, when I add the second (and subsequent) UITableView as subzones, they do not rotate properly and thus appear on the side. This is only checked in the simulator. Here is a small code:

- (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 on the side. Comment on addSubview for viewB and viewA will appear correctly. Do this only for viewA, and viewB will appear correctly.

I do not create these UITableViewControllers via NIB, although UIWindow.

If you're interested, ShellTVC is a UITableViewController and implements this method:

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

In addition, I set UIInterfaceOrientation in the plist file to UIInterfaceOrientationLandscapeLeft.

Perhaps related and unanswered - SO questions here and here .

+3
iphone landscape
Oct 27 '09 at 16:38
source share
6 answers

I think I understood the way — perhaps the right way — to do it.

  • Create a subclass of "master" UIViewController that implements shouldAutorotate ... and add this as the only view in your window.
  • To alternate between viewA or viewB, use a combination of rejectModalViewControllerAnimated: and presentModalViewController: animated: on this main view controller.

Here is the 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 it work?

  • All orientation changes flow through view controllers, not views.

  • As far as I can tell, the first view or subheading that you add to the window gets a special sauce. If there is a view controller in this view, the window displays it.

That is, for the first nested view, you can recall this code:

 [window addSubview:masterVC.view]; 

like something like this (not a real method!):

 [window addSubview:masterVC.view withViewController:masterVC]; 

I do not understand about this anymore. I find the fact that I can do this from the first spy, but not with others, highly puzzling. More information is welcome, and please let me know if this helped you or not.

+7
Apr 11 '10 at 2:36
source share

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 this might be the only workaround.

+1
Apr 10 2018-10-10T00:
source share

Unfortunately, your subtitles only ask you what orientations they support when the orientation changes.

So, I finish setting the orientation before I push the new view controller on the stack if I know that it has changed:

 [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 

Yes, this is an unsupported call.

0
Oct. 27 '09 at 17:49
source share

You can use the UIApplication object to force the orientation of a specific device.

 [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; 
0
Oct 27 '09 at 18:53
source share

Yes, I believe that you need to solve this problem with multiple XIBs. I remember that I saw this decision through one of the books that I read in the past. If not, you play with the translation and the position of the object in the view ... it is better to have a separate XIB.

-one
Aug 27 '10 at 15:10
source share

That 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); } } 
-one
Dec 10 '10 at 8:43
source share



All Articles