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







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
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?
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
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!
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.
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
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…
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 :-)
Propilotapps
March 5, 2013 at 12:14 am
Thank you for the tutorial. How can I preload data from a plist? Thank you.