Defaulting Core Data data

Rod Liberal

If your app relies on default data that needs to be shipped with the app release, there are several ways of accomplishing such task.
If your data is contained in plists, then populating those lists at first launch is a viable and common solution.

But what about getting the same result when using core data?

My app relies on a lot of initial default data which not only needs to be available to the user at first launch, but is also mutable data which the user can update.

First off, I wanted to use my app itself to populate the default data. The reason for this is to use all the data validation and formatting that is already available within the app to load the data. Also, I’ve spent hours upon hours in the simulator updating and using this data, so no need to reinvent the wheel with a different tool to load it.
Core Data saves all of your app data into a sqlite database file which, in turn, is a flat file easily transportable. Here’s how to do it:

First, run your app in the simulator and enter all the data you need into your app through your UI.
Again, core data will create a sqlite flat file that you can get to, so from Xcode, under your Source group, choose Add/Existing Files… and navigate to your app’s documents directory and select the sqlite file that contains your default data. Make sure the “Copy items into destination group’s folder” check mark is checked and click Add.

(The document directory for your app (for iOS 4.1) will be in <user>/Library/Application Support/iPhone Simulator/4.1/Applications//Documents where <user> will your user folder (Rod in my case) and <applicationFolder> is a GUID which may look like 3C17B9C8-76CE-4089-B77E-221968BB3CA5)

Now, there’s a little bit of code you need to add to make this all work, so let’s get into your app’s Application Delegate implementation file and look for the persistenceStoreCoordinator method.

This method is where your database file gets created in the app’s documents if it doesn’t already exist, upon application launch. Right before your persistence store gets initialized…

persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

You want to add the following bit of code:


//First, check to see if sqlite db exists in documents already
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; // get documents directory

NSString* toFile = [documentsPath stringByAppendingPathComponent:@"My_Sweet_App.sqlite"];

BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:toFile];

//if not, copy from bundle to docs (if file in bundle exists)
if (!fileExists) {
NSString *fromFile = [[NSBundle mainBundle] pathForResource:@"My_Sweet_App" ofType:@"sqlite"]; // gets path for file in bundle i.e. the default sql file you added to your Source group

fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fromFile];

if (fileExists) {
[[NSFileManager defaultManager] copyItemAtPath:fromFile toPath:toFile error:nil]; // copy from bundle to documents
}
}

What you’re basically doing here is checking to see if this is the first time the user is using your app. If it is, you copy your default db (the one you added to your Source group) to the documents folder so it’s available to be compiled into the momd.

This raises questions regarding updates to your db in later releases, but it’s nothing that versioning and migrations can’t handle.


One Response to “Defaulting Core Data data”

Leave a Reply