Code_Snippet

Thursday Tech Tip – Adding Core Data & Git to Existing Xcode Projects

Add_FrameworkI learned two valuable lessons when working with Xcode projects this week. A lot of times developers will create Proof of Concept (POC) projects wherein they will not use all the potential features offered; in this case Core Data in Xcode. If you’re lucky, you may find you have hit on something and want to expand the capabilities of a project. You can often just import a framework from the ¬†Project Overview screen in Xcode like to the right here. For most frameworks, merely adding the framework and including the reference to it in the header file of your desired class is enough. For Core Data, you have to go a bit further than this.

#import <CoreData/CoreData.h>


When adding Core Data to your app you have to make some edits in your AppDelegate .h and .m files to be able to leverage Core Data in your app. The three most essential steps are:

  1. Add Core Data framework to your app.
  2. Add a Core Data model to your app.
  3. Edit the AppDelegate files as I will outline below.

Again to add the framework, just go into the main project view and click on the “+” button under the “Linked Frameworks and Libraries” section. Search for Core Data, select it and then click add. After that, the framework will appear in “Frameworks” folder in your project navigator. After that, you need to add a Core Data model. To do that, Select “File > New File (or Command + N)” from the menu bar. From the next screen, select “Core Data” under “iOS” and then name it. Be careful of what you name it, as changing the name later could break a lot of connections. Most devs name the model after the app unless they plan on managing multiple databases. After adding the model, you can build out your entities or wait for later; it is not required that you have a complete model first. In my example I will create a “User” Entity and sample attributes.

Add_Data_Model

Next comes the App Delegate updates. Essentially you want your files to have the additions below. Also, you will want to update the error handlers to your needs. By default they abort and kill the app. Don’t worry, there will be a link at the end of this post to download the demo files I created.

AppDelegate.h:

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

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

AppDelegate.m:

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

- (void)applicationWillTerminate:(UIApplication *)application {[self saveContext];}
- (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();
        }
    }
}

#pragma mark - Core Data stack

- (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:@"demo" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

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

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"demo.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

- (NSURL *)applicationDocumentsDirectory { return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; }

The most important aspect of the code above is that in your .m file, make sure that the values for the strings used in defining the storeURL and modelURL are set to the same value as the name of your data model (i.e. data model name equals “demo,” values for modelURL and storeURL should be “demo”). After that, the very last thing to do is make sure that the Core Data data model is included in the Build Phases of your project. To do that, go to the project detail screen, click on the add button under “Copy Bundle Resources,” select your xcdatamodelId file and click add. You should see something like below if successful. Once done, you can start to code leveraging core data methods for fetching and writing data without issue.

The other tip I wanted to share today was on how to add a Git repo to your Xcode project if you chose not to at the beginning. This process is way easy. Simply quit Xcode after saving the latest version of your project. Open up a terminal window and type in the terminal commands below. Once complete, you will notice that when you reopen your project, you will see that under “Source Control” in the Menu bar, you now can see your branches (master only initially) and can start pulling, pushing, and merging away. Xcode apparently is smart enough to identify a GIT repo addition automatically.

cd Desktop/Demo/ #path to your project
git init
git add 
.git commit -m "Initial commit"

The link to the demo project is here.

Leave a Reply