Wednesday, March 9, 2011

Loading xib files in iPad/iPhone Universal app

Note: This blog is deprecated. @synthesize zach has moved to a new home, at zpasternack.org. This blog entry can be found on the new blog here. Please update your links.

I'm making an iPad enhanced version of PuzzleTiles, and have thus been doing a lot of reading on doing Universal apps.

One thing just about every Universal app has to do is to have separate xib files, because the iPhone and iPad have completely different form factors. I've stumbled across this idiom continuously in the past few days:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
    mainMenu = [[MainMenu alloc] initWithNibName:
                 @"MainMenu-iPad" bundle:nil]; 
}else{  
    mainMenu = [[MainMenu alloc] initWithNibName:
                 @"MainMenu" bundle:nil]; 
}

Well, that's all well and good, but it turns out that initWithNibNamed:bundle: supports device modifiers. So instead of the above, you can use this:

mainMenu = [[MainMenu alloc] initWithNibName:
             @"MainMenu" bundle:nil]; 

The magic is in the file naming. Name your files "MainMenu.xib" for the iPhone version and "MainMenu~ipad.xib" for the iPad version. iOS will automatically load the device-specific version when running on that device. Much easier, no?

I found no official Apple documentation which explicitly states that the device modifier mechanism works for xib files, but it definitely works, back to iOS 4.0, near as I can tell. Relevant StackOverflow question here. I'm always on the lookout for ways to remove code, so I'll take it.

Update: As noted below in the comments, device modifiers are case sensitive, so make sure you're doing "MyView~ipad.xib", not "MyView~iPad.xib", or else the magic won't work. Relevant Apple documentation here.

6 comments:

  1. Aww, snap, a post not having to do with UIAlertView! w00t!

    Nice job, dude.

    ReplyDelete
  2. Look, I thought we had a deal: you don't mention my fixation on UIAlertView, and I won't mention your fixation on BBW porn. Whoops!

    ReplyDelete
  3. Fair deal. Carry on.

    I mean, I've no idea what you're talking about.

    ReplyDelete
  4. I've been testing out the "SomeView~iPad.xib" concept that automatically works when you are running iPad. What I am finding is that it only works on the iPad simulator. Whenever I test and a physical device it just loads the smaller iPhone XIB instead which iOS attempts to make look like the iPad size. Interesting. Looks like I'm back to specifying the idiom stuff all over the place. Thanks anyhow :)

    ReplyDelete
  5. "SomeView~iPad.xib" won't work, because device modifiers (on device, anyhow) are case sensitive. If you change it to "SomeView~ipad.xib", it should work fine on device. I have shipping code which does this.

    ReplyDelete
  6. These things aren't case-sensitive when using the simulator, but are when using the device. This is something that you have to be careful about in this instance, and also with image names e.g. Default.png and default.png, otherwise you'll find your splash screen won't appear on the device.

    Another reason why you need to test code on a real device as well as the simulator.

    ReplyDelete