Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Core data prepop article

  • Loading branch information...
commit fd6613c3ed5b0401843a2dc4da45701680775848 1 parent 98e5d9e
Zach authored

Showing 1 changed file with 131 additions and 0 deletions. Show diff stats Hide diff stats

  1. +131 0 _posts/2013-03-26-ios-core-data-prepopulation.md
131 _posts/2013-03-26-ios-core-data-prepopulation.md
Source Rendered
... ... @@ -0,0 +1,131 @@
  1 +---
  2 +layout: post
  3 +title: "iOS Core Data Prepopulation"
  4 +description: ""
  5 +category: code
  6 +tags: [iOS, core data]
  7 +---
  8 +{% include JB/setup %}
  9 +
  10 +When developing a mobile app, it's necessary to ship the app with some default
  11 +data. I recently came across the task of pre-populating an application with a
  12 +fair amount of data and found documentation on exactly how to do this with Core
  13 +Data lacking. Maybe it's because I'm not a seasoned Core Data expert, but
  14 +come on! Searching The Google also turned up many others having a similar hard
  15 +time finding clarity on this issue.
  16 +
  17 +This article presents a method for pre-populating a Core Data application on
  18 +IOS.
  19 +
  20 +#### Procedure
  21 +We'll walk through the specific steps in detail, but this is the general
  22 +approach to Core Data pre-population:
  23 +
  24 +1. Generate a Core Data database with pre-populated data
  25 +2. Add this database to the project
  26 +3. When app starts for the first time, copy the pre-populated DB into the
  27 + managed store and start application.
  28 +4. Profit!
  29 +
  30 +#### Step 1: Generate a Core Data database
  31 +
  32 +A common misconception about Core Data is that 'its just a sqlite database,
  33 +gosh! ' Which is true; however sqlite is just one of the ways Core Data can
  34 +persist itself. The problem with this conception is the Core Data sqlite
  35 +schemea is proprietary - don't even try opening it up with any tools because
  36 +the data and column names won't make any sense. Changing anything may render
  37 +the DB unusable. What we need to do is somehow populate the DB via the Core
  38 +Data interface. This may require writing our own parsing code, or using an app
  39 +like [Core Data Editor](http://christian-kienle.de/CoreDataEditor)
  40 +
  41 +In apps I've done, data was first extracted as JSON, manually parsed, and then
  42 +saved within Core Data.
  43 +
  44 +#### Step 2: Add the pre-populated database to the project
  45 +Add the function we've created to parse and prepopulate Core Data somewhere within the Appdelegate, or
  46 +another place to be executed on launch. Next, within the AppDelegate, we need to find the
  47 +location of our newly populated sqlite file. Add this code to the
  48 +'persistentStoreCoordinator' in AppDelegate :
  49 +
  50 +{% highlight objective-c %}
  51 +- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
  52 + /* ... */
  53 + NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Foobar.sqlite"];
  54 + NSLog(@"CoreData Location: %@", storeURL);
  55 +{% endhighlight %}
  56 +
  57 +Awesome, now we gotcha!
  58 +Rename this file to something like 'Prepopulated.sqlite' and add it to project
  59 +as a resource.
  60 +
  61 +#### Step 3: Core Data switcheroo
  62 +
  63 +This code taken from Apple example project [Core Data Books](https://developer.apple.com/library/ios/#samplecode/CoreDataBooks/Listings/Classes_CoreDataBooksAppDelegate_m.html#//apple_ref/doc/uid/DTS40008405-Classes_CoreDataBooksAppDelegate_m-DontLinkElementID_8)
  64 +
  65 +Replace the method 'persistentStoreCoordinator' within AppDelegate with this
  66 +one. Notice places in the code to fill in for your respective DB names.
  67 +
  68 +{% highlight objective-c %}
  69 +- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
  70 +{
  71 + if (_persistentStoreCoordinator != nil) {
  72 + return _persistentStoreCoordinator;
  73 + }
  74 +
  75 + NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"PREPOPULTED_NAME.sqlite"];
  76 +
  77 + /*
  78 + Set up the store.
  79 + For the sake of illustration, provide a pre-populated default store.
  80 + */
  81 + NSFileManager *fileManager = [NSFileManager defaultManager];
  82 + // If the expected store doesn't exist, copy the default store.
  83 + if (![fileManager fileExistsAtPath:[storeURL path]]) {
  84 +
  85 + // typically the main store name is 'appName.sqlite'
  86 + NSURL *defaultStoreURL = [[NSBundle mainBundle] URLForResource:@"YOURAPPNAME" withExtension:@"sqlite"];
  87 + if (defaultStoreURL) {
  88 + [fileManager copyItemAtURL:defaultStoreURL toURL:storeURL error:NULL];
  89 + }
  90 + }
  91 +
  92 + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
  93 + _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
  94 +
  95 + NSError *error;
  96 + if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
  97 + /*
  98 + Replace this implementation with code to handle the error appropriately.
  99 +
  100 + abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
  101 +
  102 + Typical reasons for an error here include:
  103 + * The persistent store is not accessible;
  104 + * The schema for the persistent store is incompatible with current managed object model.
  105 + Check the error message to determine what the actual problem was.
  106 +
  107 +
  108 + If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
  109 +
  110 + If you encounter schema incompatibility errors during development, you can reduce their frequency by:
  111 + * Simply deleting the existing store:
  112 + [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
  113 +
  114 + * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
  115 + @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
  116 +
  117 + Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
  118 +
  119 + */
  120 + NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
  121 + abort();
  122 + }
  123 +
  124 + return _persistentStoreCoordinator;
  125 +}
  126 +{% endhighlight %}
  127 +
  128 +#### Step 4: Profit
  129 +
  130 +That's it! Hopefully this approch worked out and your app can now ship with
  131 +pre-populated data.

0 comments on commit fd6613c

Please sign in to comment.
Something went wrong with that request. Please try again.