Core Data Basics
Episode
#11
|
22 minutes
| published on
April 19, 2012
Free Video
Core Data is Apple's framework for persisting data on Mac & iOS. It can be though of as an ORM, however it's probably a lot different than most ORMs you've used in the past. In this episode, we'll set up Core Data from scratch so you can see all the moving parts.
Want more? Subscribers can view all 473 episodes. New episodes are released regularly.
Links
- Episode Sample Code
- Core Data Book - Marcus Zarra - This is considered the best reference on Core Data out there.
- iOS Recipes - The data model technique I used in the episode came from this book. Highly recommended!
- Mogenerator - This tool generates classes based on your data model. I barely scratched the surface of this tool in the screencast, but this is widely used and could be considered standard practice. Be aware, though, that Xmo'd doesn't yet work in Xcode 4, so you'll have to use the script directly.
- Core Data Programming Guide - Apple's official documentation
Setting up Core Data
// BeersDataModel.h
#import <CoreData/CoreData.h>
@interface BeersDataModel : NSObject
+ (id)sharedDataModel;
@property (nonatomic, readonly) NSManagedObjectContext *mainContext;
@property (nonatomic, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (NSString *)modelName;
- (NSString *)pathToModel;
- (NSString *)storeFilename;
- (NSString *)pathToLocalStore;
@end
// BeersDataModel.m
#import "BeersDataModel.h"
@interface BeersDataModel ()
@property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
- (NSString *)documentsDirectory;
@end
@implementation BeersDataModel
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize mainContext = _mainContext;
+ (id)sharedDataModel {
static BeersDataModel *__instance = nil;
if (__instance == nil) {
__instance = [[BeersDataModel alloc] init];
}
return __instance;
}
- (NSString *)modelName {
return @"Beers";
}
- (NSString *)pathToModel {
return [[NSBundle mainBundle] pathForResource:[self modelName]
ofType:@"momd"];
}
- (NSString *)storeFilename {
return [[self modelName] stringByAppendingPathExtension:@"sqlite"];
}
- (NSString *)pathToLocalStore {
return [[self documentsDirectory] stringByAppendingPathComponent:[self storeFilename]];
}
- (NSString *)documentsDirectory {
NSString *documentsDirectory = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
return documentsDirectory;
}
- (NSManagedObjectContext *)mainContext {
if (_mainContext == nil) {
_mainContext = [[NSManagedObjectContext alloc] init];
_mainContext.persistentStoreCoordinator = [self persistentStoreCoordinator];
}
return _mainContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel == nil) {
NSURL *storeURL = [NSURL fileURLWithPath:[self pathToModel]];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:storeURL];
}
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator == nil) {
NSLog(@"SQLITE STORE PATH: %@", [self pathToLocalStore]);
NSURL *storeURL = [NSURL fileURLWithPath:[self pathToLocalStore]];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *e = nil;
if (![psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&e]) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:e forKey:NSUnderlyingErrorKey];
NSString *reason = @"Could not create persistent store.";
NSException *exc = [NSException exceptionWithName:NSInternalInconsistencyException
reason:reason
userInfo:userInfo];
@throw exc;
}
_persistentStoreCoordinator = psc;
}
return _persistentStoreCoordinator;
}
@end
Generating the entities with Mogenerator
mogenerator --template-var arc=true --model Beers.xcdatamodeld/Beers.xcdatamodel
(Note in the video I had the --template-var
setting after the model, and that's why the setting wasn't actually applied)
Saving Data
NSManagedObjectContext *context = [[BeersDataModel sharedDataModel] mainContext];
if (context) {
NSLog(@"Context is ready!");
Beer *beer = [Beer insertInManagedObjectContext:context];
beer.name = @"90 Minute Imperial IPA";
Brewery *brewery = [Brewery insertInManagedObjectContext:context];
brewery.name = @"Dogfish Head";
beer.brewery = brewery;
[context save:nil];
} else {
NSLog(@"Context was nil :(");
}