2

I have a universal app for iOS 8/9 which contains a MainStoryboard_iPhone and a MainStoryboard_iPad. The entry point in the storyboard is a RootViewController with a Tab Bar. The RootViewController controller is quite simple

- (void)viewDidLoad
{
[(VIBAppDelegate *)[[UIApplication sharedApplication] delegate] setRootViewController:self];
self.interfaceOrientationMask = UIInterfaceOrientationMaskAll;
self.preferredOrientation = UIInterfaceOrientationMaskAll;
[super viewDidLoad];}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return self.interfaceOrientationMask;
}

- (BOOL)shouldAutorotate{
return YES;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    UIViewController *currentVC = self.selectedViewController;
    if ([currentVC respondsToSelector:@selector(preferredInterfaceOrientationForPresentation)]) {
        UIInterfaceOrientation orientation = [currentVC preferredInterfaceOrientationForPresentation];
        return orientation;
    }else{
    return self.preferredOrientation;
    }
}

When I launch this app on an iPhone the supportedInterfaceOrientation and shouldAutorotate methods are called during app startup and whenever the device rotates. When I launch the app on an iPad they are never called. In both cases the viewDidLoad function is called as expected.

I have been puzzling over this for hours. I see no differences in the storyboards other than layout. Both device types allow for all 4 orientations and other relevant keys from the Info.plist file.

<key>UIMainStoryboardFile</key>
<string>MainStoryboard_iPhone</string>
<key>UIMainStoryboardFile~ipad</key>
<string>MainStoryboard_iPad</string>
<key>UIStatusBarHidden</key>
<true/>
<key>UIStatusBarHidden~ipad</key>
<true/>
<key>UIStatusBarStyle</key>
<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
    <string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationPortraitUpsideDown</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
</array>

Putting breakpoints at the shouldAutorotate function shows that is is being called by UIWindow _shouldAutorotateToInterfaceOrientation:checkForDismissal:is... which is called by UIApplicationMain. This is as expected.

BruceT
  • 23
  • 4
  • Okay, so... Since on iPad you are allowing all four orientations, and since `supportedInterfaceOrientations` is returning All as well, what's the problem? The app is rotating, right? And that's what you are saying to do, right? – matt Oct 04 '15 at 01:31
  • If you notice supportedInterfaceOrientationMask returns the value of a class variable. This variable is set by various view controllers to control which particular orientations are allowed by each tab. This works on the iPhone as these orientation related methods are all called as the device rotates. On the iPad they are never called making it impossible to control the orientations. It makes no sense why they are called on one platform and not on the other. – BruceT Oct 04 '15 at 02:50
  • Just FYI, it's not a class variable. It's an instance variable. – matt Oct 04 '15 at 02:52
  • Okay, so, see the answer here: http://stackoverflow.com/a/31771093/341994 I think you'll find that if you check that checkbox, all will be well. – matt Oct 04 '15 at 02:54
  • First, you are right, it is an instance variable. My mistake. My solution was to watch for the rotation and then use an affine transform to rotate it to the correct orientation. This is not ideal because the OS rotates it first and then I rotate it back. I wish there was a smoother way to handle but this works well enough. – BruceT Oct 05 '15 at 00:54

1 Answers1

6

On iOS 9, an iPad app by default opts into iPad multitasking. This means that it must adopt all orientations at all times. Since you have not opted out of iPad multitasking, the runtime assumes that you do adopt all orientations at all times — and thus it doesn't need to bother to ask you what orientations you permit, as it already knows the answer (all of them).

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I thought that might have been related to the problem. I just completed reworking the app for iOS 9 multitasking but there is one view which needs to be fixed. I will need to rework this part of the app... – BruceT Oct 04 '15 at 12:42
  • If you add UIRequiresFullScreen=YES in info.plist, then shouldAutorotate will be called on iPad on iOS 12 at least. – poGUIst Mar 25 '19 at 16:44
  • @poGUIst Yes, that's what I said. If you add UIRequiresFullScreen=YES, then you are opting _out_ of iPad multitasking. But the OP did not do that. Therefore the runtime asks no questions about orientations; it knows all the answers already. – matt Mar 25 '19 at 16:48