RSS

Core Data Basics Part 5 – Preloading Data

21 Feb


Introduction

Pre-loading default data into Core Data can be as simple or difficult as you make it. Some factors that may or may not complicate the task are:

  • What format the data is currently in
  • How much data you need to import

The format of the existing data is the biggest issue.  If it’s in database format your import code will be different than if it is in xml format. If it’s just a small list of things in text format then you can probably skip the whole import business and copy/paste your data directly into your code. If you want to know how to parse XML you should read and apply principles covered in Game Template Part 3 – Game Data Persistence.  I’m going to focus on where and how to write data from code into Core Data.

Prerequisites

We follow on from Part 4, so download the project from the end of Part 4 then extract and open it with Xcode.

Inserting Default Data

To insert default data we need to detect when the default import is required. One way to do that is to to select a count of items within a particular entity we’re interested in.  The most appropriate place for this check is just after Core Data has been set up – i.e. when the Persistent Store & Object Model & Context are ready.  Typically this is in AppDelegate.m so insert the following code at the top of the existing didFinishLaunchingWithOptions method:

    [self setupFetchedResultsController];
 
    if (![[self.fetchedResultsController fetchedObjects] count] > 0 ) {
        NSLog(@"!!!!! ~~> There's nothing in the database so defaults will be inserted");
        [self importCoreDataDefaultRoles];
    }
    else {
        NSLog(@"There's stuff in the database so skipping the import of default data");
    }

Obviously you’re going to need the setupFetchedResultsController method so also add the following above the existing didFinishLaunchingWithOptions method. You should be familiar with setupFetchedResultsController as we have used it a few times already. I’ve customised it to fetch the Role entity:

- (void)setupFetchedResultsController
{
    // 1 - Decide what Entity you want
    NSString *entityName = @"Role"; // Put your entity name here
    NSLog(@"Setting up a Fetched Results Controller for the Entity named %@", entityName);
 
    // 2 - Request that Entity
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
 
    // 3 - Filter it if you want
    //request.predicate = [NSPredicate predicateWithFormat:@"Person.name = Blah"];
 
    // 4 - Sort it if you want
    request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name"
                                                                                     ascending:YES
                                                                                      selector:@selector(localizedCaseInsensitiveCompare:)]];
    // 5 - Fetch it
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                        managedObjectContext:self.managedObjectContext
                                                                          sectionNameKeyPath:nil
                                                                                   cacheName:nil];
    [self.fetchedResultsController performFetch:nil];
}

The other thing you need now are methods to import all the defaults. In these methods you could set up a whole bunch of stuff to parse and import from DB/XML/whatever. Your data mapping is really up to you to customise as you need it. You’ll get the idea from this below code, which you should paste above the setupFetchedResultsController method:

- (void)insertRoleWithRoleName:(NSString *)roleName
{
    Role *role = [NSEntityDescription insertNewObjectForEntityForName:@"Role"
                                               inManagedObjectContext:self.managedObjectContext];
 
    role.name = roleName;
 
    [self.managedObjectContext save:nil];
}
 
- (void)importCoreDataDefaultRoles {
 
    NSLog(@"Importing Core Data Default Values for Roles...");
    [self insertRoleWithRoleName:@"C/C++ Developer"];
    [self insertRoleWithRoleName:@"Obj-C Developer"];
    [self insertRoleWithRoleName:@"Java Developer"];
    [self insertRoleWithRoleName:@"ASP.NET Developer"];
    [self insertRoleWithRoleName:@"Unix Engineer"];
    [self insertRoleWithRoleName:@"Windows Engineer"];
    [self insertRoleWithRoleName:@"Business Analyst"];
    [self insertRoleWithRoleName:@"Infrastructure Manager"];
    [self insertRoleWithRoleName:@"Project Manager"];
    [self insertRoleWithRoleName:@"Operations Manager"];
    [self insertRoleWithRoleName:@"Desktop Support Analyst"];
    [self insertRoleWithRoleName:@"Chief Information Officer"];
    NSLog(@"Importing Core Data Default Values for Roles Completed!");
}

Those methods we’ve just added will be giving you a bunch of errors so you’ll need to add the following to AppDelegate.h

#import <CoreData/CoreData.h>
@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;

Also add the following to AppDelegate.m

@synthesize fetchedResultsController = __fetchedResultsController;

Testing the Import

If you’ve already run the Staff Manager app once (and have entered Roles into the Simulator) then you will need to click iOS Simulator > Reset Content and Settings to ensure that there is no data in the database.  Once you’ve done that run the app and you should see default roles when you select the Roles tab. Note also the log entries telling you that defaults were inserted.  They should only fire once!

That’s it for this tutorial.  I know it was a pretty short one however I wanted you to focus on just getting data  into Core Data from code.

Here’s the complete source code so far

If you liked this tutorial or found something wrong with it please let me know!

If you want to support my work and have an iPad please consider purchasing iSoccer *wink*

-Tim

Go to Part 6 or the Tutorials Index


Be Sociable, Share!
 

About Tim Roadley

I'm a 30 something year old married-with-children Infrastructure Manager living in Australia and working at Cuscal. I love iOS coding and have found the most effective way to learn (and retain) is by writing tutorials. I love getting feedback and helping like minded people learn iOS too :)
14 Comments

Posted by on February 21, 2012 in iOS Tutorials

 

14 Responses to Core Data Basics Part 5 – Preloading Data

  1. Erasmo Pinheiro

    February 22, 2012 at 4:07 am

    Hi Tim,
    Thanks a lot.

    I’m studing CoreData for developer my first App.
    I was getting concepts piece by piece in many sites.
    All I have studied is in your very good tutorial.

    I have some concerns about leave my NSManagedObjectContext opened (kind of) while users enter in background mode.
    Do you know about something ? If it’s cause some batery lacks ?
    Thanks a lot

     
  2. Tim Roadley

    February 23, 2012 at 7:14 am

    Erasmo,

    I’m glad you like the tutorial. As far as I’m aware keeping NSManagedObjectContext open when the app enters the background doesn’t use any additional battery. Only things that stay active in the background would consume more battery I think. If you can find some further information around about this I’d be interested to learn otherwise!

    Cheers

     
    • zagoox

      February 8, 2013 at 8:09 am

      Love your tutorial! how create a UILocalizedIndexedCollation on person?

       
  3. adrian phillips

    February 27, 2012 at 2:26 am

    once a gain great job. it is quiet descriptive when it comes to core data. thanks again for taking the time to write this tutorial.

    adrian

     
  4. Chris

    March 14, 2012 at 11:11 pm

    Hi Tim,

    you are missing the “insertRoleWithRoleName:” method in the guide. Otherwise, it’s great.

    Regards,
    Chris

     
    • Tim Roadley

      March 17, 2012 at 8:20 pm

      Oh thanks for pointing that out, fixed!

       
  5. Johnny

    March 26, 2012 at 12:17 pm

    I’m trying to adopt your preloading for multiple attributes on the same entity. Can you point me to any sources that would allow me to expand on your work?

    I’m using custom table view cells, each with four labels and I can’t seem to wrap my head around the logic (I’m a web designer by trade).

    Thanks for these great tuts – my knowledge has grown by leaps and bounds!

    Take care and thanks again.

     
  6. Graham Gardiner

    May 8, 2012 at 2:24 am

    Hi Tim

    Fantastic tutorial really well laid out thank you very much.
    I have a question How would I link the Name to more than one Role.
    ie: Name: Graham Gardiner: Role: Taxi Driver, Car wash director, Panel beater
    So The name would be on a label at the top and the roles would be listed on a table below. Can you help or give me any info

    Thanks and regards
    Graham

     
  7. Swatee

    June 30, 2012 at 4:56 pm

    Hey thanx alot.. I m always confused to use to which database to be add in my app tht coredata or sqlite..
    But due to this post got relax to use coredat can be preloaded…
    Again thanx…

     
  8. TickTack

    June 30, 2012 at 6:51 pm

    No need to “iOS Simulator > Reset Content and Settings”. Just run the app, stop it and in simulator, delete applike you normally do on device. Hold icon and once it starts shaking, tap the black cross to delete. Once you run the app again, it will not have any data in CoreData database and import defaults :-)

     
  9. Propilotapps

    March 5, 2013 at 12:14 am

    Thank you for the tutorial. How can I preload data from a plist? Thank you.

     

Leave a Reply