Monday, August 9, 2010

Loading device specific .xib files in a Universal app

While working on the update to Fridgemags I came across an issue loading the proper .xib file for the correct device.  Apple docs state that the device will dynamically load the correct corresponding files using the following convention: <mainName><device_modifier>.<filename_extension>.  That is to say if you have MainView.xib and MainView~ipad.xib in the same location and it should load the correct .xib file

Now, Apple's documentation may say one thing but due to the organization of our code, an issue with the simulator or Apple's implementation I was not getting the correct .xib file to load for the correct device.  Also, this does not work with older versions of iOS.

To allow for these exceptions I've replaced the standard init method:
- (id)init {
  self = [super initWithNibName:@"MainView" bundle:nil];
  if ( ! self) return nil;
}

With the following init method:
- (id)init {
  NSMutableString *nibName = [NSMutableString stringWithString:@"MainView"];
  if ([UIDevice instancesRespondToSelector:@selector(userInterfaceIdiom)]) {
    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
      [nibName appendString:@"~ipad"];
    }
  }
  self = [super initWithNibName:nibName bundle:nil];
  if ( ! self) return nil;
}

Now the app will check to see if UIDevice responds to userInterfaceIdiom and if it's UIUserInterfaceIdiomPad then load the MainView with "~ipad" appended to it.

This can be further simplified by creating a category and creating a new method such as initWithUniversalNibName:bundle:.

1 comment:

atomicbird said...

For what it's worth, in the current version of Apple's docs they only mention device_modifier in relation to images. They may have fixed the docs since your post, I have no way to tell, but since they use "basename" while you use "mainName" it might have been that the docs have changed since your post.

I only mention this because I tried this scheme with a nib and it failed, but as far as I can tell this naming convention isn't supposed to work in that case.