Thursday, October 09, 2008

On iPhone Splash Screens

Craig Hockenberry posted today about why Twitteriffic for iPhone/iPod touch uses a splash screen. I have considered the splash screen a number of times for iTimeZone 1.1, but ultimately decided to continue to include a screenshot of the app to make it appear like its starting fast. I actually added more to Default.png so that the illusion is perhaps better, here is the 1.0 to 1.1 side by side:

1.01.1

But it would be so much better if, as Craig suggest, the iPhone OS would save a PNG whenever asked, then load that instead. I don't think this is really voodoo, or something hard for Apple to do. Seems like the logic is just this easy:

  1. If Default.png exists in user's application document folder (i.e. the NSDocumentDirectory of NSUserDomainMask) load it
  2. Else, load Default.png from the bundle root
  3. No step 3
Should be a new option in Info.plist that can be set to automatically have iPhone OS create the user Default.png at application shutdown, or the app can do that itself if desired.

I spun up a quick sample project to test if this was already implemented in iPhone OS 2.1 undocumented, but it doesn't appear to be unless I stuck the user Default.png in the wrong spot. I used the same method from iTimeZone 1.1 to copy a user writable SQLite database, which itself was pretty much straight out of Apple's SQLite Books Sample, to copy a Default.png into the application specific user document folder:

- (void)createUserDefaultPNGIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableUserDefaultPath = [documentsDirectory stringByAppendingPathComponent:@"Default.png"];
success = [fileManager fileExistsAtPath:writableUserDefaultPath];

if (success) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultUserDefaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Default-users.png"];

success = [fileManager copyItemAtPath:defaultUserDefaultPath toPath:writableUserDefaultPath error:&error];
if (!success) {
NSAssert1(0, @"Failed to create user Default.png file with message '%@'.", [error localizedDescription]);
}
}

The variables at runtime look like this:

It doesn't work. If I change NSDocumentDirectory to NSApplicationSupportDirectory, I actually get an NSException that No such file or directory exists.. I didn't walk through the paths to figure out which one, Library or Application Support are not there, I suspect both. Here are my variables using NSApplicationSupportDirectory:

So I created the whole path doing this [fileManager createDirectoryAtPath:documentsDirectory attributes:nil]; and was then able to put a Default.png in the NSApplicationSupportDirectory. Still, iPhone OS did not load the user's Default.png instead of the bundle's Default.png.