dhrm
dhrm

Reputation: 14944

Core data: how to use default database?

I've created a default iOS application in Xcode with Core Data. I've placed a default myDatabase.sqllite file in my project, which I would like to use the first time the application starts -- so every user does not have to fetch all new items.

How can I change the code in the AppDelegate.m to use my default myDatabase.sqllite first time the application starts?

Upvotes: 2

Views: 802

Answers (2)

Paul.s
Paul.s

Reputation: 38728

I normally create my persistant store and pre-seed it in the simulator, which is nice and fast compared to on the device especially if data is coming from the network or XML. I then copy the output (.sqlite) of that file into the project bundle.

Then when you start the app do a check and if the database does not exist in the place where the persistant store coordinator looks then copy your pre-seeded database from your bundle into the correct place.

I believe this is what the documentation @simon talks about is referring to when it says create a separate persistant store and copy it into place.

Updated
Take a look at NSFileManager it has the following method

- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error

Discussion
...If a file with the same name already exists at dstPath, this method aborts the copy attempt and returns an appropriate error.

due to the previous fact you can probably get away with just using that method and not trying to do any

- (BOOL)fileExistsAtPath:(NSString *)path

which cold potentially lead to race conditions.

Therefore before your NSPersistentStoreCoordinator is loaded you need to do something like:

NSString *seededDatabasePath = [[NSBundle mainBundle] pathForResource:@"myDB" ofType:@"sqlite"];

NSError *error = nil;
BOOL didCopy = [[NSFileManager defaultManager] copyItemAtPath:seededDatabasePath
                                                       toPath:fileDatabasePath
                                                        error:&error];

if (!didCopy) {
    // .. make sure that the error isn't something bad
}

Upvotes: 4

Simon
Simon

Reputation: 9021

I'm not sure you can do this. The usual method is to populate your Core Data tables from either XML or PLists at runtime. I personally have a version stamp in the user defaults which I check on application launch. If it's not found (or wrong version) I run an XML parser to pull in default data.

I'm interested to see the outcome of this one though, to see if anyone has found a better method.

EDIT: Just found this in mac programming guide and assume it's similar for iPhone...

You can create a separate persistent store that contains the default data and include the store as an application resource. When you want to use it, you must either copy the whole store to a suitable location, or copy the objects from the defaults store to an existing store.

For small datasets, you can create the managed objects directly in code.

You can create a property list—or some other file-based representation—of the data, and store it as an application resource. When you want to use it, you must open the file and parse the representation to create managed objects.

You should not use this technique on iOS, and only if absolutely necessary on Mac OS X. Parsing a file to create a store incurs unnecessary overhead. It is much better to create a Core Data store yourself offline and use it directly in your application.

Furthermore, I found this too....

How do I use my existing SQLite database with Core Data?

You don’t. Although Core Data supports SQLite as one of its persistent store types, the database format is private. You cannot create a SQLite database using native SQLite API and use it directly with Core Data (nor should you manipulate an existing Core Data SQLite store using native SQLite API). If you have an existing SQLite database, you need to import it into a Core Data store (see “Efficiently Importing Data”).

Upvotes: 1

Related Questions