12
votes

My app has been in the AppStore for a couple of months now and always only worked on iPhone. I recently submitted an update which was rejected because the App does not run on an iPad. The exact reason it was rejected was:

Reasons for Rejection: 2.10: iPhone apps must also run on iPad without modification, at iPhone resolution, and at 2X iPhone 3GS resolution

What do I need to do in Xcode to make my app run on an iPad in the little box with the 2X icon?

Any tips instructions will be massively appreciated...

EDIT This is my info.plist. This is my first App and I think I did initially chose to set it up with "universal" selected. Is there an easy way back for me to rectify this now?

PLIST contents...

6
Have you tried running it on the iPad simulator? Do you have @2x images?Jamie

6 Answers

10
votes

Start by figuring out why your app doesn't work on the iPad already. Most apps developed for the iPhone will work fine on an iPad (in compatibility mode) with no modification; if yours doesn't, you must be doing something to prevent it. Are you relying on some hardware feature? Making unfounded assumptions about the device you're running on? How does your app fail when run on an iPad?

Once you've figured out why it doesn't work, you'll be much closer than you are now to fixing the problem.

7
votes

To get your app to run on an iPad in iPhone compatibility mode, you need to build your app for iPhone only.

Remove all the iPad references from the app's plist (nib base, xib and storyboard), and from the Target Build Settings Targeted Device Family.

4
votes

I had the same issue, I was able to run my app on the ipad after making the following changes.

  1. in the project settings made the Devices to iPhone(it was universal before)
  2. in the .plist removed the main story board file base name related to ipad.
1
votes

I have solved same issue using this scenario.

You should check for normal and retina images in your resources folder.

You may also get this error while debugging Could not load the "image.png" image referenced from a nib in the bundle with identifier.

A normal iPhone app must run on the iPad in both(1x and 2x) mode without modification. You can check this with the SDK Simulator.

There is a long list in the App Store Review Guidelines on Apple's iOS Developer Portal Center which lists many of the things that Apple reviews this things when you submit an app. Read it carefully.

0
votes

I'll try to explain what my problem and solution was..

I have an iPhone only app which is mostly in portrait, however, because of 1 or 2 UIViewControllers which have to be in all UIInterfaceOrientations, I have to enable all UIInterfaceOrientations in my plist.

When starting the app on an iPad which is rotated in landscape and is lying on the table (so has UIDeviceOrientationFaceUp), the whole app was shown in landscape, which made my UI totally messed up.

I had no reference to any iPad related code / settings in my plist or launch screens whatsoever (I am using .xcassets for launch screens).

I fixed it by adding 1 line of code to my AppDelegate.m which sets the statusbar orientation to force the app in portrait mode.

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];

    //Further setup
}
0
votes

I had the same issue using Cocos2d 2.0

My problem was that the project had evolved over several years and had carried along some now vestigial files like RootViewController and UIViewController and MyRootViewController, etc.

They worked at the time but clearly had raised a flag with today's review committee because I received the "All iPhone apps must work on the iPad" rejection notice. After screaming out loud and finally accepting defeat, I thought that policy makes it pretty hard to make an app iPhone only. Let me know if I am wrong about this.

Even though I was (and am still) perturbed about it, I thought perhaps now I could at least clean up the project with a more elegant solution that handles the base problem: device rotation + content rotation. I ended up using something from a more recent project that was working on and seemed more elegant and actually worked: simply add MyNavigationController to the top of my AppDelegate.

I have added the code below. I am sure it can be improved. Please comment if you can enhance it.

As a result, I was able to delete the old RootViewController and MyRootViewController files so now it's easier to maintain. I never understood their purpose very well anyways. Good riddance!

Here is my solution to displaying and matching device orientation + content orientation:

in AppDelegate.h I had to declare what I was doing:

//top of the file

@interface MyNavigationController : UINavigationController @end

//inside AppDelegate.h interface

MyNavigationController *navController_;

//bottom of the file before @end

@property (readonly) MyNavigationController *navController;

Here is the code that works at the top of my AppDelegate.m

@implementation MyNavigationController

// The available orientations should be defined in the Info.plist file.
// And in iOS 6+ only, you can override it in the Root View controller in the "supportedInterfaceOrientations" method.
// Only valid for iOS 6+. NOT VALID for iOS 4 / 5.

-(NSUInteger)supportedInterfaceOrientations {

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

if (orientation == UIDeviceOrientationPortrait) {

    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

        // [director_ pushScene: [IPAD scene]];

    } else {

        [[CCDirectorIOS sharedDirector] pushScene:[VerticalDisplayLayer scene]];

        return UIInterfaceOrientationMaskPortrait;

    }


} else if (orientation == UIDeviceOrientationLandscapeLeft) {


    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

       //  [director_ pushScene: [IPAD scene]];

    } else {

        [[CCDirectorIOS sharedDirector] pushScene:[MainMenuScene scene]];

    }



} else if (orientation == UIDeviceOrientationLandscapeRight) {


    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

        // [director_ pushScene: [IPAD scene]];

    } else {

        [[CCDirectorIOS sharedDirector] pushScene:[MainMenuScene scene]];

    }


} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {

    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

    } else {

        [[CCDirectorIOS sharedDirector] pushScene:[VerticalDisplayLayer scene]];

        return UIInterfaceOrientationMaskPortraitUpsideDown;

    }

} else {

    //do nothing
}

return UIInterfaceOrientationMaskLandscape;

}

//this is the one for iOS 6
- (BOOL)shouldAutorotate {

//NSLog(@"MyNavigationController - should Rotate ToInterfaceOrientation ...");

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

// iPhone only
if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ) {

    //NSLog(@"MyNavigationController - should Rotate iPhone");

    if (orientation == UIDeviceOrientationPortrait) {

        //NSLog(@"should Rotate iPhone orientation is Portrait");

        [[CCDirectorIOS sharedDirector] pushScene:[VerticalDisplayLayer scene]];

        return UIInterfaceOrientationMaskPortrait;

    }

    if (orientation == UIDeviceOrientationPortraitUpsideDown) {

        //NSLog(@"should Rotate iPhone orientation is PortraitUpsideDown");

        [[CCDirectorIOS sharedDirector] pushScene:[VerticalDisplayLayer scene]];

        return UIInterfaceOrientationMaskPortraitUpsideDown;

    }

    if (orientation == UIDeviceOrientationLandscapeLeft) {

        //NSLog(@"should Rotate iPhone orientation is Landscape Left");

        return UIInterfaceOrientationMaskLandscape;
    }

    if (orientation == UIDeviceOrientationLandscapeRight) {

        //NSLog(@"should Rotate iPhone orientation is Landscape Right");

        return UIInterfaceOrientationMaskLandscape;
    }


    return TRUE;

}

//return UIInterfaceOrientationIsLandscape(interfaceOrientation);

if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ) {

    //NSLog(@"MyNavigationController - should Rotate iPad");

    return TRUE;

}


return TRUE;
}


// Supported orientations. Customize it for your own needs
// Only valid on iOS 4 / 5. NOT VALID for iOS 6.
- (BOOL)shouldAutorotateToInterfaceOrientation:    (UIInterfaceOrientation)interfaceOrientation
{

// iPhone only
if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone )


    return TRUE;
//return UIInterfaceOrientationIsLandscape(interfaceOrientation);


if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad )

    return TRUE;

// iPad only
// iPhone only
//return UIInterfaceOrientationIsLandscape(interfaceOrientation);

return TRUE;
}

// This is needed for iOS4 and iOS5 in order to ensure
// that the 1st scene has the correct dimensions
// This is not needed on iOS6 and could be added to the application:didFinish...
-(void) directorDidReshapeProjection:(CCDirector*)director
{
if(director.runningScene == nil) {
    // Add the first scene to the stack. The director will draw it immediately into the framebuffer. (Animation is started automatically when the view is displayed.)
    // and add the scene to the stack. The director will run it when it automatically when the view is displayed.
    [director runWithScene: [MainMenuScene scene]];
}
}


-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
// Assuming that the main window has the size of the screen
// BUG: This won't work if the EAGLView is not fullscreen

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect rect = CGRectZero;

//NSLog(@"MyNavigationController - Will RotateToInterfaceOrientation ...");

if(toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)  {

    rect = screenRect;


} else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {

    rect.size = CGSizeMake( screenRect.size.height, screenRect.size.width );

}

CCDirector *director = [CCDirector sharedDirector];
CCGLView *glView = (CCGLView *)[director view];
glView.frame = rect;
}

@end

Here is why I had to solve this:

  1. I needed both Landscape and Portrait modes to display different scenes.

Here are some screenshots that describe the situation

JR Chemistry Set

most of the app orientation is landscape like this photo shows

other areas were only triggered when you turned the device

2 apps in one!