views:

1429

answers:

3

I'm working on a new app that I want to be universal for the iPhone and iPad. I started out with the "Create a Window-based app" wizard, and it created separate app delegates in "iPhone" and "iPad" groups. Since I already was quite familiar with iPhone dev, I did that part of my project, and now I'm ready to do some iPad stuff.

So... I started out by adding a UISplitViewController to my iPad delegate, switch the Active SDK to 3.2, and it works! But when I switch back to 3.1.3, and try to run it in the simulator, Build and Go fails. For starters, I see:

...path.../iPad/AppDelegate_Pad.h:13: error: expected specifier-qualifier-list before 'UISplitViewController'

I've got my Base SDK set to 3.2 and my Deployment Target set to 3.1.3. I thought that was enough. But I also have found in the documentation this method to conditionally compile:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
   MyIPadViewController* vc;
// Create the iPad view controller
#else
   MyIPhoneViewController* vc;
// Create the iPhone view controller
#endif

So do I need to do this everywhere? It seems like an awful lot of code to add (that I'll be getting rid of in a short time for 4.0 anyway) so I feel like I must be doing something wrong. And, I don't even have any idea how this works for things like @property or @synthesize declarations.

tl;dr version of the question - did I miss a setting somewhere?

+3  A: 

Quite the opposite. A universal app runs the same binary on iPhone and iPad so you cannot use conditional compilation to differentiate between the two version. But you need to use the macro Apple cites in the documentation:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    // iPad-specific code
} else {
    // iPhone-specific code
}
Ole Begemann
So how I add something like to a header file, where I'm declaring a variable of type UISplitViewController? I'm supposed to have an if/else block in it?
bpapa
No, you can just declare it. Build for iPhone Device 3.2 and it will run on your 3.0/3.1 device.
Ole Begemann
The conditional compilation blocks are useful if you want to test your app in the iPhone 3.1 Simulator, though (because the 3.2 Simulator does not support running a universal app in iPhone mode).
Ole Begemann
You can still declare the 3.2 type of variable since your Base SDK is 3.2, just don't use it if you're running on 3.1.3. Your code that uses it has to be in conditional statements.
progrmr
OK, I guess I should have mentioned that I am trying to run this in the simulator. :) So I actually can't test Universal apps on the simulator, but only the device? Please kill me now.
bpapa
You can test universal apps in the iPad simulator and/or on a real iPhone. You just can't test them in the iPhone simulator, at least for now (unless you can compile it with 3.1.3 Base SDK, which I gave up on, too many #ifdef's).
progrmr
OK actually I was supremely confused, even when I wrote the question, and I re-edited it. The problem I am really having - when I add code that is specific to 3.2, and switch to running the app on the 3.1.3 simulator, it fails.
bpapa
How is it failing? Compilation errors on the 3.2 only stuff? That's because you're compiling with the 3.1.3 Base SDK and it doesn't have those definitions. See my previous comment. If you really must test on the iPhone simulator, you'll have to be able to compile with the 3.1.3 Base SDK which means #ifdef's around any 3.2 stuff since it won't compile there.
progrmr
You can also do this: (1) Build for the 3.2 Simulator. (2) Switch the Active SDK to the 3.1.3 Simulator. (3) Run without rebuilding. This should open the app in the 3.1.3 iPhone Simulator. It's a hassle because you have to switch back and forth between builds, though.
Ole Begemann
+7  A: 

I use this C function to help keep the code concise:

BOOL isPad() {
#ifdef UI_USER_INTERFACE_IDIOM
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#else
    return NO;
#endif
}

Another thing I do, when I have different xib files for iPhone vs iPad. I have a stripPadSuffixOnPhone() function that helps keep the code simpler:

// Load/create the Delete table cell with delete button
self.deleteCell = [Utilities loadNib:stripPadSuffixOnPhone(@"DeleteCell~ipad") 
                           ClassName:@"DeleteCell" 
                   Owner:self];

Things like that can make coding more straightforward and a lot less conditionals. Still have to test everything twice though.

progrmr
A: 

Here's what works for me:

  1. Build your app using SDK 3.2.
  2. Switch the active SDK to iPhone Simulator 3.1.3 (or whatever).
  3. From the Run menu select Debug (not Build and Debug).

The binary built under 3.2 will be installed in the 3.x simulator without rebuilding. When you are finished don't forget to set your active SDK back to 3.2.

Bob Withers
The stock install of the 3.2 SDK deletes the 3.1.x SDKs, so you can't set them as the active SDK.
Shaggy Frog