iPhone development has been a great experience but that does not mean it has not been without its challenges. For instance, if you are planning on saving some sort of dynamic content in your application, you will quickly find that it is not simply a matter of discovering where your application is being stored and writing some files in there.  It is a little bit more involved than that.  In order to help those who come after, we thought it would be worthwhile to share some of our findings.

I think the first thing to realize is that when your application is deployed onto your iPhone/iPod/Simulator you are deploying a complete package. This means that the contents, i.e your code, resources, database and anything else that might be part of your deployment bundle are uniquely signed using your developer’s key which verifies that everything you intended to be in there is there and nothing else. This is a very important concept from a security standpoint and it allows the target device to verify the validity of the bundle to ensure that your application has not been compromised. Now that we have stated that, it’s pretty obvious that it will be impossible to change the deployed project. This doesn’t mean that Apple didn’t think of this inevitability.

The first step to looking into this deployment will be looking at the target deployed file system. The easy way to find this is to log the applications bundle path in the applicationDidFinishLoading method on the appDelegate. You can do this with the following code:

NSLog(@”Application Directory: %@”, NSHomeDirectory());

The output (in the console) for this will show you where you can find the file system. I usually just copy and paste this into a terminal window and jump right to it (just make sure to wrap the directory name in double quotation marks).

If you navigate tot this directory you will see your application (yourapp.app) which is a directory containing all of your code and resources and a Documents and a Library directory. That Documents directory is where our dynamic content will reside.

This seems straightforward enough, just put what we need in the directory and away we go, right? Well not so quick cowboy, there is no idea of an installer that executes when your application downloads. This means we are going to have to figure out how to copy the files into the Documents directory the first time the application loads.

Over here at BeefyApps, we developed this little snippet of code to handle this initial load of data.

-(void)initializeDocumentDirectory
{

NSFileManager *manager = [NSFileManager defaultManager];
NSArray *templateDir = [manager directoryContentsAtPath:[NSString stringWithFormat:@”%@/Documents”, [[NSBundle mainBundle] bundlePath]]];

for (id file in templateDir) {

if ([manager fileExistsAtPath:[NSString stringWithFormat:@”%@/Documents/%@”, NSHomeDirectory(), file]])

continue;

NSString *srcPath = [NSString stringWithFormat:@”%@/Documents/%@”, [[NSBundle mainBundle] bundlePath], file];
NSString *dstPath = [NSString stringWithFormat:@”%@/Documents/%@”, NSHomeDirectory(), file];

NSError *error;
[manager copyItemAtPath:srcPath toPath:dstPath error:&error];

}

}

So the code above simply takes a look inside of the bundle, navigated to via the [[NSBundle mainBundle] bundlePath] command. The result of this call will provide you with the string location of the applications executing bundle directory. For the purposes of this code we have a Documents directory which resides inside of the bundle path. We then take the contents of that directory and conditionally copy it file by file into the writable Documents directory.

Pretty simple solution really. I think where this gets interesting is when we start to consider the ramifications for updating your application. I’ll leave that exercise up to the reader at this time though.