Load SQLite Db Into Core Data in iOS 5
UPDATE: I’ve tried using RestKit to seed my db and it’s much easier. I wrote a blog post about it if you’re interested.
Many Model-View-Controller frameworks have a way to specify seed data (initial data for an application to function).
iOS does not. So we have to create another app that builds the database, and then have the main app copy that database and set it as default when the app first loads.
Let’s create that new app and call it UtilityApp and make sure it has the same Core Data Model as our main app:
Copy the SQLite database (which you want to use to populate our Core Data) in the “Supporting Files” in XCode:
Now either in your AppDelegate.m or in a new class, you need to populate your Core Data with the sqlite database data. I made a class called DrugFetcher.h with a public method:
1
|
|
We need to import sqlite3:
1
|
|
However, to have access to that, we need to add it from the “Build Phases” tab of our project:
Here’s my DrugFetcher.m
The script above opens the SQLite db, and adds each row to a model.
Now the “seed” database is prepared. We need get it from the UtilityApp and add it to our main app’s resources. You can run the Utility app on your desktop and then find the path where your Application is running and copy the db from there.
I prefer to ssh into the device just for my peace of mind that it was created on the target device. You’ll need to jailbreak your device to ssh into it, a process which I covered here.
To copy the file you run something like this on your device:
1
|
|
On your computer, I recommend opening the ‘persistentStore’ with sqlite3 and making sure there are no extra tables, and delete all the contents of the Z_METADATA table. I’ve run into issues with this before.
1 2 |
|
Add the persistentStore (a SQLite db) to the main app Supporting Files.
Now, in your main app, you’ll want to change your AppDelegate a bit to make sure it uses the new db. If it’s the first time the app is loaded, it will copy the persistentStore to Documents/CoreDataStore.sqlite. From then on, it will use CoreDataStore.sqlite as its data store.
We’ll use NSPersistentStoreCoordinator to achieve this. Here’s my AppDelegate.h:
The copying on first load is achieved in the persistentStoreCoordinator method, like so:
Then, in the same persistentStoreCoordinator method, we add our new store to the persistentStoreCoordinator:
Here’s the full AppDelegate.m for reference:
I realize this gets confusing, so ask questions below. I’ve wasted plenty of my time loading data, so maybe this post saves some of yours.