Monday, April 5, 2010

A Few More Notes on Creating Universal Apps

Now that I've had some more time with the iPad and making Universal Apps, I've realized there are some important things I left out of Saturday's post.

First, I talked about the newly defined macro UI_USER_INTERFACE_IDIOM(). There's a problem with this right now, however, because iPhone OS 3.2 was an iPad only release. Most of us are assuming that iPhone and iPad will eventually run on the same OS version, but for now they don't ,and UI_USER_INTERFACE_IDIOM() doesn't exist in 3.1.2 and earlier. So, if you're creating a Universal Binary, you can't compile code that uses it.

Instead, you need to use a different technique, which is the check the precompiler definition __IPHONE_OS_VERSION_MAX_ALLOWED, which is set to the OS version number without dots. The definition is five digits, the first is the major release number, the second and third are the minor release number, and the fourth and fifth number are the patch release number. So, 3.2 would be defined to 30200 and 3.1.2 would be defined to 30102, so here's how you should probably design your code for the time being:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
NSLog(@"iPad Idiom");
else
#else
NSLog(@"iPhone Idiom");
#endif


In the future, you won't need to check this, but it won't hurt to after. Since it's resolved during pre-compilation, there are no drawbacks other than a little bit of code clutter.

I forgot to mention that there's an option to upgrade Targets to Universal under the Project menu. It will convert your target for you, and you should use it instead of manually setting the project (the way I did my first few). If the option is grayed out, make sure that your project's base SDK (not just the currently selected SDK) is iPhone Device 3.0+. If it's older, or if it can't find the Base SDK, you won't get the option.

This option will do a few things. It will update your Base SDK to 3.2 and your Deployment SDK to the original Base SDK. It will configure your targets either to create a Universal Application, or two separate applications. It will create your application's main iPad NIB for you. It will strip out the ARM6 instructions from the iPad portion of the binary.

Note: As a few people have pointed out in the comments, UI_USER_INTERFACE_IDIOM() works just fine in Universal Apps. Where you can't use it is if you want to test your universal app's iPhone functionality in the simulator. The 3.2 Simulator only works in iPad configuration, so to test the iPhone build on the simulator, you need to set the Active SDK to 3.1.2, and this check will allow your code to compile against the 3.1.2 Simulator target. If you're testing on the device, the code above is unnecessary (but also doesn't hurt anything). Sorry for the confusion.

No comments:

Post a Comment