10

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?

bpapa
  • 21,409
  • 25
  • 99
  • 147

3 Answers3

39

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

BOOL isPad() {
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}

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
  • 75,956
  • 16
  • 112
  • 147
23

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
  • 135,006
  • 31
  • 278
  • 256
  • 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 May 03 '10 at 15:50
  • 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 May 03 '10 at 15:53
  • 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 May 03 '10 at 15:54
  • 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 May 03 '10 at 15:56
  • 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 May 03 '10 at 15:59
  • 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 May 03 '10 at 16:07
  • 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 May 03 '10 at 16:07
  • 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 May 03 '10 at 16:09
  • 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 May 03 '10 at 16:12
  • thanks man, i totally forgot this one and i needed it for a universal project I'm working on. its so cool having answers like this around SO. – Adrian P Feb 12 '15 at 16:31
0

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.