Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Supporting Universal App with Portrait Orientation on iPhone and Landscape+Portrait on iPad

I need my app to be compatible both on iPad and iPhone. Its having a tabbarController as the rootViewController.

In iPad I need it to be available both on Landscape and Portrait. In iPhone though I need the rootView to be Portrait itself and i do have some viewsControllers, which are being presented on the tabbarController, which need to be available both in landscape and Portrait (e.g. a viewController used to play videos from Youtube). So I am locking the rotation of the tabbarController as follows (In the UITabbarController Subclass).

# pragma mark - UIRotation Methods

- (BOOL)shouldAutorotate{
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}

- (NSUInteger)supportedInterfaceOrientations{
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? UIInterfaceOrientationMaskAll : UIInterfaceOrientationMaskPortrait;
}

What I intend to do is that by locking the rotation of the rootviewController(tabbarController), I am locking all the VC's in the tabbarController(only on iPhone) and views which are presented on top of the tabbarController can rotate as per the device orientation.

THE PROBLEM

Everything works as expected until the app is launched in the landscape in the iPhone. When launched in the landscape mode the app defaults to landscape and launches the app in the landscape mode which is not intended. It should launch in the Portrait mode itself even if the device orientation is Landscape. Since I am turning off auto rotation for iPhone the app continues to be in landscape itself resulting in a bug. I tried this method to force the app to launch in portrait in the application:didFinishLaunchingWithOptions:

#pragma mark - Rotation Lock (iPhone)

- (void)configurePortraitOnlyIfDeviceIsiPhone{
    if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone))
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
}

Still the issue persists. I have allowed all orientation options on the info.plist for SupportedInterfaceOrientaions key both for iPad and iPhone since I need the app to be in landscape for iPhone even if only for a few viewControllers. The issue can be fixed if I can somehow force that app to launch in Portrait orientation even if the device orientation is Landscape. Please correct me if am wrong in the logic, if not, any help to make the app launch in the portrait mode will be appreciated.

I have already gone through this question here and here, but couldn't get it working yet.

Thank You

like image 900
Athul George Avatar asked Sep 28 '22 08:09

Athul George


1 Answers

This is how I managed to get it working. In the AppDelegate.m, I added this method.

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    //if iPad return all orientation
    if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad))
        return UIInterfaceOrientationMaskAll;

    //proceed to lock portrait only if iPhone
    AGTabbarController *tab = (AGTabbarController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    if ([tab.presentedViewController isKindOfClass:[YouTubeVideoPlayerViewController class]])
        return UIInterfaceOrientationMaskAllButUpsideDown;
    return UIInterfaceOrientationMaskPortrait;
}

This method checks every time a view is displayed for the orientation and corrects orientation as required. I return all orientation for the iPad and none for the iPhone with exception that the view which is to be presented (the one which should rotate, YouTubeVideoPlayerViewController) is left off.

And in the tabbarController subclass,

# pragma mark - UIRotation Methods

- (BOOL)shouldAutorotate{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations{
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? UIInterfaceOrientationMaskAll : UIInterfaceOrientationMaskPortrait;
}

The problem was that when we return no to shouldAutoRotate the app will ignore all rotation change notifications. It should return YES so that it will rotate to the correct orientation described in supportedInterfaceOrientations

I suppose this is how we should approach this requirement rather than passing on the rotation instructions to the respective viewControllers as many posts have said on SO. This is some advantage of using containers as recommended by Apple so that we don't have to code rotation instructions on each and every view in a container.

like image 140
Athul George Avatar answered Nov 15 '22 07:11

Athul George