Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pre-load existing data into a Core Data-based iPhone app?

In a previous project, I built an iPhone app for 2.2.x that used SQLite. It had existing data (in XML form) that needed to be pre-loaded into the build. So I wrote a small tool which used libxml2 to parse the XML, and then write out an SQLite database, which then was included directly in the build as a resource. This worked out great.

I will be starting a new project for a different client in a few weeks that has mostly the same parameters. I will have some existing data I will need to parse and dump into a file that the app will display. However, this time around I'd like to use Core Data and build the app for 3.x devices. However, I don't have explicit and direct access to the underlying database schema that Core Data uses. (Which is kind of the point of Core Data)

How can I pre-load existing data into a Core Data-based iPhone app? Can I automate the process (similar to what I did above with SQLite)?

like image 663
Shaggy Frog Avatar asked Nov 19 '09 23:11

Shaggy Frog


1 Answers

I'm a little late to this party, but i'm doing something similar for GroceryList. I have data stored in plist files that i need in my CoreData sqlite store. I wrote a command line foundation tool that runs on my Mac which parses the plist files and then using my Core Data object model creates a sqlite store. I run this command line tool as part of my build (for some build configurations) so that i can regenerate the data at will. To create this kind of tool in xcode, select File -> New Project -> Mac OS X -> Command Line Tool and select "Core Data" from the "type" menu. Here's some sample code:

#import <objc/objc-auto.h>

int main (int argc, const char * argv[]) {

    objc_startCollectorThread();

    //You may not know this, but NSUserDefaults can be used to parse command line arguments!
    //in this case, the arguments are passed in like this:
    // -fullMomPath /hd/some/path/file.mom -fullStorePath /hd/some/path/file.sql
    //by passing in the storePath, the calling script knows where the sqlite file will be and can copy it to the resulting application bundle
    NSUserDefaults *args = [NSUserDefaults standardUserDefaults];   
    NSString *momPath = [args stringForKey:@"fullMomPath"];
    NSString *storePath = [args stringForKey:@"fullStorePath"];

    // Create the managed object context
    NSManagedObjectContext *context = managedObjectContext(momPath, storePath);


    //build and save your NSManagedObjects here
    //in my case, i parse some plist files and create GroceryList type stuff, but whatever you do is your business.

    return 0;
}

NSManagedObjectModel *managedObjectModel(NSString* momPath) {

    static NSManagedObjectModel *model = nil;

    if (model != nil) {
        return model;
    }

    NSURL *modelURL = [NSURL fileURLWithPath:momPath];
    model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    return model;
}



NSManagedObjectContext *managedObjectContext(NSString* momPath, NSString* storePath) {

    static NSManagedObjectContext *context = nil;
    if (context != nil) {
        return context;
    }

    context = [[NSManagedObjectContext alloc] init];

    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel(momPath)];
    [context setPersistentStoreCoordinator: coordinator];

    NSString *STORE_TYPE = NSSQLiteStoreType;

    NSURL *url = [NSURL fileURLWithPath:storePath];

    NSError *error;
    NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:STORE_TYPE configuration:nil URL:url options:nil error:&error];

    if (newStore == nil) {
        NSLog(@"Store Configuration Failure\n%@",
              ([error localizedDescription] != nil) ?
              [error localizedDescription] : @"Unknown Error");
    }

    return context;
}
like image 93
kalperin Avatar answered Nov 13 '22 14:11

kalperin