Adding Core Data to existing project in XCode 4

18,643

Solution 1

One trick is to just create a new empty project with Core Data support. That will give you the necessary code that you can copy over to your original project and compile.

The only gotcha is that you need to handle the Core Data header file. Xcode puts it in the precompiled header files when it generates files using the templates. So you can add the following line to your .pch file:

#import <CoreData/CoreData.h>

or you can just add it to the .m files where needed.

It works like a charm. Notice Luka's comment below about how to do it in Xcode5.

Solution 2

Just to expound on all the steps you actually need to perform to add Core Data to a project that previously did not have it:

Step 1: Add the Framework

Click on your app target (on the left pane its the top icon with the name of your app) then go to the 'Build Phases' tab then on 'Link Binary With Libraries', click the little '+' at the bottom then find 'CoreData.framework' and add it to your project

Then either import coredata on all the objects you need it (the non-sexy way) using:

#import <CoreData/CoreData.h>

or add the import below the common imports in your .pch file (much more sexy) like this:

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>
#endif

Step 2: Add the Data Model

To add the .xcdatamodel file right click/control-click on your files in the right pane (like in a Resources folder for safe keeping) and select to Add a New File, Click the Core Data tab when selecting your file type then Click 'Data Model', give it a name and click Next and Finish and it will add it to your project. When you click on this Model object you will see the interface to add the Entities to your project with any relationships you want.

Step 3: Update App Delegate

Add these objects to AppDelegate.h

 @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
 @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
 @property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

 - (NSURL *)applicationDocumentsDirectory; // nice to have to reference files for core data

Synthesize the previous objects in AppDelegate.m like this:

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

Then add these methods to AppDelegate.m (make sure to put the name of the model that you added in the spots shown):

- (void)saveContext{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

- (NSManagedObjectContext *)managedObjectContext{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"NAMEOFYOURMODELHERE" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"NAMEOFYOURMODELHERE.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

 #pragma mark - Application's Documents directory

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

Step 4: Get the Data Objects to the ViewControllers Where You Need the Data

in the ViewController.h

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;

In the ViewController.m

@synthesize managedObjectContext = _managedObjectContext;

In the AppDelegate, or class where the ViewController is created set the managedObjectContext to be the same as the AppDelegate one

ViewController.managedObjectContext = self.managedObjectContext;

If you want the viewcontroller using Core Data to be a FetchedResultsController then you'll need to make sure this stuff is in your ViewController.h

@interface ViewController : UIViewController <NSFetchedResultsControllerDelegate> {
  NSFetchedResultsController *fetchedResultsController;
  NSManagedObjectContext *managedObjectContext;
}

 @property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

And this is in ViewController.m

@synthesize fetchedResultsController, managedObjectContext;

After all of that you can now use this managedObjectContext to run all the usual fetchRequests needed for CoreData goodness! Enjoy

Solution 3

If you want to add CoreData.framework to your project, double-click the Target in your Groups and Files list. Go to the Summary pane, and click the "+" for Linked Libraries. Choose CoreData.framework. It will then link with your project.

Solution 4

Xcode adds a bundle of stuff into the standard template for Core Data.

If you are not familiar with it then create a new Core Data project and push your own stuff into it rather than trying to add the infrastructure to your existing project.

Basically what you get is...

  • An empty Core Data model.
  • Init code for the Core Data stack
Share:
18,643

Related videos on Youtube

adit
Author by

adit

Updated on June 13, 2022

Comments

  • adit
    adit almost 2 years

    I started off the project without Core Data and now I would like to add that functionality to my apps. How do I do this?

    What additional things does XCode sets up when you actually tick the Use Core Data when you create a new project?

  • adit
    adit almost 13 years
    I was actually going to do this, however I had a bunch of frameworks linked in (three20, etc)
  • adit
    adit almost 13 years
    does it modify any of the project build settings?
  • Monolo
    Monolo almost 13 years
    Sorry if I wasn't clear - the idea is to copy the useful code over from a vanilla template generated by Xcode just for that purpose. You maintain all of your existing Xcode project.
  • Warren Burton
    Warren Burton almost 13 years
    Depends if you are using Document architecture or a simple view based app. You probably get some info.plist setup too. Spawn one and have a poke around.
  • adit
    adit almost 13 years
    so from xcode generated template to my existing project not the other way around
  • Monolo
    Monolo almost 13 years
    Yup - and since it could very easily be misunderstood, I have edited the answer. Thanks for the heads-up.
  • Shea Daniels
    Shea Daniels over 12 years
    I thought it might help people to know that the "Use Core Data" option is not available in the Single View Based Application template in Xcode. You have to choose Empty Application instead.
  • abc123
    abc123 about 11 years
    Don't forget to add the CoreData framework in. Xcode 4.6: In project navigator click your project, your app in Targets, Summary tab, plus sign in Linked Frameworks and Libraries.
  • abc123
    abc123 about 11 years
    And change the string names in - (NSPersistentStoreCoordinator *)persistentStoreCoordinator and - (NSManagedObjectModel *)managedObjectModel
  • mkc842
    mkc842 almost 11 years
    @SKG Thanks for pointing out the need to link the framework. I don't know what you mean about changing the string names, though. I searched for those names in my project and nothing looked fishy. Could you clarify?
  • lgdev
    lgdev over 10 years
    In Xcode 5.0 you can select the "Master-Detail Application" or "Empty Application" template in order to get the "Use Core Data" option, and have the Core Data code generated.
  • Peng90
    Peng90 about 10 years
    Great answer, one thing to notice is in the appDelegate header file, the method - (NSString *)applicationDocumentsDirectory; should be - (NSURL *)applicationDocumentsDirectory;. Otherwise it won't match the code in - (NSPersistentStoreCoordinator *)persistentStoreCoordinator. I've edited the answer with updated code.
  • SushiGrass Jacob
    SushiGrass Jacob almost 10 years
    Thank you for these complete instructions. This should be the correct answer.