Core Data is an object graph and persistence framework that allows storing and managing objects and relationships between objects. The Core Data stack includes the managed object model, persistent store coordinator, managed object context and persistent stores. Entities are represented by NSManagedObject subclasses and stored in a persistent store like SQLite. The managed object context acts as an in-memory scratch pad and saves changes to the persistent store. Queries use NSPredicate to fetch managed objects. Core Data handles object lifecycles and relationships and automatically saves changes between the context and store.
2. Who Am I?
Scott Ahten, Ahten Industries
Technologist, iOS Developer
scott@ahtenindustries.com
3. Topics Covered
What is Core Data?
When should I use Core Data?
Framework overview
Using Core Data
Migrations
Threading & concurrency types
4. What is Core Data
Not a Database!
Not an Object Relational Mapping framework
5. What is Core Data
Object Persistence Framework
CRUD operations
Queries using NSPredicate
Aggregate queries
Multiple persistent store
Available on iOS and Mac OS X Desktop
7. Core Data vs. SQLite
SQLite Core Data
Multiple Update YES NO
Multiple Delete YES NO
Auto Populate Objects NO YES
Custom SQL YES NO
Automatic
Lightweight Migrations NO YES
Speed YES YES
Model Objects NO YES
8. When Should I
Use CoreData?
Use CoreData?
Wrong Question
When Shouldn’t I use Core Data?
Really Fast - Highly Optimized by Apple
All but trivial and special cases
You should be using Model objects
9. Core Data and MVC
View
View Controller
Controller
Model
Model
Core Data
14. NSPersistentStoreCoordinator
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Example_App.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;
}
15. NSPersistentStoreCoordinator
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Example_App.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;
}
16. NSPersistentStoreCoordinator
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Example_App.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;
}
17. NSPersistentStoreCoordinator
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Example_App.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;
}
18. NSManagedObjectModel
Schema for Models
Entities, properties, relationships, etc.
Validations
Fetch Requests
Configurations
Objective-C Subclass
23. Relationships
NSSet, not NSArray
One to one
One to many and many to many
Minimum and maximum count
Ordered returned NSOrderedSet (iOS 5>=)
Delete Rules
Nullify, Cascade, Deny
24. NSManagedObjectModel
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Example_App" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
25. NSManagedObjectModel
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Example_App" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
26. NSManagedObjectModel
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Example_App" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
27. NSManagedObjectContext
Scratch Pad for Entities
Queried objects are pulled into context
Can be Faulted
Entities inserted into context
Changes are not persisted until calling save:
29. NSManagedObjectContext
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
30. NSManagedObjectContext
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
31. Saving
Save occurs per context
Saves changes to persistent store
Should save on applicationWillTerminate:
Can be reset to discard changes
32. Saving
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
// Replace this implementation with code to handle the error appropriately.
}
}
}
33. NSManagedObject
Represents an entity in your model
Superclass of managed object subclasses
Access attributes via KVC/KVO and properties
Pass NSManagedObjectIDs between threads
Xcode can generate subclass with accessors
Can be a fault
34. Querying Entites
NSPredicate
Rich query syntax
Aggregate property values
Compound predicates
Queries can return faulted entities based on result
type
Batch size
41. Inserting Entities
Insert into managed object context
Entities are not yet persisted until context is saved
42. Inserting Entities
- (void)insertNewObject:(id)sender
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name]
inManagedObjectContext:context];
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the
template.
[newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
}
}
43. Inserting Entities
- (void)insertNewObject:(id)sender
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name]
inManagedObjectContext:context];
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the
template.
[newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
}
}
44. Inserting Entities
- (void)insertNewObject:(id)sender
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name]
inManagedObjectContext:context];
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the
template.
[newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
}
}
45. Inserting Entities
- (void)insertNewObject:(id)sender
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name]
inManagedObjectContext:context];
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the
template.
[newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
}
}
46. Deleting Entites
Entities are marked as deleted
No longer returned in queries
Not actually deleted until context is saved
Deletes can be discarded before save by discarding
or resetting the context
47. Deleting Entites
- (void)deleteEvent:(NSManagedObject*)event
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSError *error = nil;
[managedObjectContext deleteObject: event];
if (![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
}
}
48. Updating Entities
Same as insert
Change properties and save context
Updates can be discarded before save by discarding
or resetting the context
49. Migrations
Schemas change
Create new model version
Automatic lightweight migration
Manual migration
Not all changes require migration
Validation, default values, Objective-C class
50. Concurency Types
iOS 5 >=
NSConfinementConcurrencyType
Pre iOS 5 Concurrency
NSPrivateQueueConcurrencyType
Private dispatch queue
NSMainQueueConcurrencyType
Main Queue
51. Resources
Core Data Programming Guide
http://developer.apple.com/library/mac/#
documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html
Predicate Programming Guide
http://developer.apple.com/library/mac/#
documentation/Cocoa/Conceptual/Predicates/predicates.html
Grand Central Dispatch (GCD)
http://developer.apple.com/library/ios/#
documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/referen
ce.html