Date post: | 12-May-2015 |
Category: |
Technology |
Upload: | andrew-kozlik |
View: | 535 times |
Download: | 5 times |
INTRODUCTIONINTRODUCTIONTO CORE DATATO CORE DATA
Orlando iOS Developer GroupOrlando iOS Developer Group01/23/201301/23/2013
AHTEN INDUSTRIESScott AhtenScott Ahten
Who Am I?Who Am I?
Scott Ahten, Ahten IndustriesScott Ahten, Ahten Industries
Technologist, iOS DeveloperTechnologist, iOS Developer
[email protected]@ahtenindustries.com
Topics CoveredTopics Covered
What is Core Data?What is Core Data?
When should I use Core Data?When should I use Core Data?
Framework overviewFramework overview
Using Core DataUsing Core Data
MigrationsMigrations
Threading & concurrency typesThreading & concurrency types
What is Core DataWhat is Core Data
Not a Database!Not a Database!
Not an Object Relational Mapping frameworkNot an Object Relational Mapping framework
What is Core DataWhat is Core Data
Object Persistence FrameworkObject Persistence Framework
CRUD operationsCRUD operations
Queries using NSPredicateQueries using NSPredicate
Aggregate queriesAggregate queries
Multiple persistent storeMultiple persistent store
Available on iOS and Mac OS X DesktopAvailable on iOS and Mac OS X Desktop
Persistent Persistent Store TypesStore Types
BinaryBinary
In MemoryIn Memory
XML (Desktop Only)XML (Desktop Only)
SQLiteSQLite
Custom TypesCustom Types
Core Data vs. SQLiteCore Data vs. SQLite
SQLiteSQLite Core DataCore Data
Multiple UpdateMultiple Update YESYES NONO
Multiple DeleteMultiple Delete YESYES NONO
Auto Populate ObjectsAuto Populate Objects NONO YESYES
Custom SQLCustom SQL YESYES NONOAutomaticAutomatic
Lightweight MigrationsLightweight Migrations NONO YESYES
SpeedSpeed YESYES YESYES
Model ObjectsModel Objects NONO YESYES
When Should IWhen Should IUse CoreData?Use CoreData?
Wrong QuestionWrong Question
When Shouldn’t I use Core Data?When Shouldn’t I use Core Data?
Really Fast - Highly Optimized by AppleReally Fast - Highly Optimized by Apple
All but trivial and special casesAll but trivial and special cases
You should be using Model objectsYou should be using Model objects
Core Data and MVCCore Data and MVC
ControlleControllerr
ControlleControllerr
ViewViewViewView
ModelModelModelModel
Core DataCore Data
Model ObjectsModel Objects
NSManagedObject subclassNSManagedObject subclass
Lifecycle eventsLifecycle events
ValidationValidation
FaultingFaulting
Undo SupportUndo Support
RelationshipsRelationships
Core Data FrameworkCore Data Framework
ApplicationApplicationApplicationApplication
NSManagedObjectNSManagedObjectNSManagedObjectNSManagedObject
NSManageObjectContextNSManageObjectContextNSManageObjectContextNSManageObjectContext
NSPersistentStoreCoordinatorNSPersistentStoreCoordinatorNSPersistentStoreCoordinatorNSPersistentStoreCoordinator NSManageObjectModelNSManageObjectModelNSManageObjectModelNSManageObjectModel
NSPersistentStoreNSPersistentStoreNSPersistentStoreNSPersistentStore
XMLXMLXMLXML SQLiteSQLiteSQLiteSQLite BinaryBinaryBinaryBinary MemoryMemoryMemoryMemory CustomCustomCustomCustom
Core Data StackCore Data Stack
Setup in App DelegateSetup in App Delegate
Xcode Core Data templateXcode Core Data template
NSPersistentStoreCoordinatorNSPersistentStoreCoordinator
Coordinates access to one or more persistent Coordinates access to one or more persistent storesstores
Managed Object ModelManaged Object Model
Set store optionsSet store options
NSPersistentStoreCoordinatorNSPersistentStoreCoordinator
// 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;}
NSPersistentStoreCoordinatorNSPersistentStoreCoordinator
// 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;}
NSPersistentStoreCoordinatorNSPersistentStoreCoordinator
// 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;}
NSPersistentStoreCoordinatorNSPersistentStoreCoordinator
// 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;}
NSManagedObjectModelNSManagedObjectModel
Schema for ModelsSchema for Models
Entities, properties, relationships, etc.Entities, properties, relationships, etc.
ValidationsValidations
Fetch RequestsFetch Requests
ConfigurationsConfigurations
Objective-C SubclassObjective-C Subclass
NSManagedObjectModelNSManagedObjectModel
Attribute TypesAttribute Types
Integer TypesInteger Types
DecimalDecimal
DoubleDouble
FloatFloat
StringString
BooleanBoolean
DateDate
Binary DataBinary Data
Other Types?Other Types?
Serialize to NSData via NSCoderSerialize to NSData via NSCoder
Value Transformer and Transformable typeValue Transformer and Transformable type
Opaque to QueriesOpaque to Queries
NSManagedObject subclassNSManagedObject subclass
Attribute OptionsAttribute Options
TransientTransient
OptionalOptional
IndexedIndexed
Default ValuesDefault Values
Store in external record file (iOS 5 >=)Store in external record file (iOS 5 >=)
RelationshipsRelationships
NSSet, not NSArrayNSSet, not NSArray
One to oneOne to one
One to many and many to manyOne to many and many to many
Minimum and maximum countMinimum and maximum count
Ordered returned NSOrderedSet (iOS 5>=)Ordered returned NSOrderedSet (iOS 5>=)
Delete RulesDelete Rules
Nullify, Cascade, DenyNullify, Cascade, Deny
NSManagedObjectModelNSManagedObjectModel
// 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;}
NSManagedObjectModelNSManagedObjectModel
// 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;}
NSManagedObjectModelNSManagedObjectModel
// 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;}
NSManagedObjectContextNSManagedObjectContext
Scratch Pad for EntitiesScratch Pad for Entities
Queried objects are pulled into contextQueried objects are pulled into context
Can be FaultedCan be Faulted
Entities inserted into contextEntities inserted into context
Changes are not persisted until calling save:Changes are not persisted until calling save:
NSManagedObjectContextNSManagedObjectContext
Not thread safe!Not thread safe!
One context per thread One context per thread
More than one context per coordinatorMore than one context per coordinator
Merge notificationsMerge notifications
Concurrency Types (iOS 5>=)Concurrency Types (iOS 5>=)
Blocks, GCD queuesBlocks, GCD queues
NSManagedObjectContextNSManagedObjectContext
// 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;}
NSManagedObjectContextNSManagedObjectContext
// 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;}
SavingSaving
Save occurs per contextSave occurs per context
Saves changes to persistent storeSaves changes to persistent store
Should save on applicationWillTerminate:Should save on applicationWillTerminate:
Can be reset to discard changesCan be reset to discard changes
SavingSaving
- (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. } }}
NSManagedObjectNSManagedObject
Represents an entity in your modelRepresents an entity in your model
Superclass of managed object subclassesSuperclass of managed object subclasses
Access attributes via KVC/KVO and propertiesAccess attributes via KVC/KVO and properties
Pass NSManagedObjectIDs between threadsPass NSManagedObjectIDs between threads
Xcode can generate subclass with accessorsXcode can generate subclass with accessors
Can be a faultCan be a fault
Querying EntitesQuerying Entites
NSPredicateNSPredicate
Rich query syntaxRich query syntax
Aggregate property valuesAggregate property values
Compound predicatesCompound predicates
Queries can return faulted entities based on Queries can return faulted entities based on result typeresult type
Batch sizeBatch size
FaultsFaults
Only object IDOnly object ID
Performance & memoryPerformance & memory
Include specific propertiesInclude specific properties
Prefetch relationshipsPrefetch relationships
Querying EntitesQuerying Entites
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];[request setSortDescriptors:sortDescriptors];
NSError *error = nil;NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];if (mutableFetchResults == nil) { // Handle the error.}
Querying EntitesQuerying Entites
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];[request setSortDescriptors:sortDescriptors];
NSError *error = nil;NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];if (mutableFetchResults == nil) { // Handle the error.}
Querying EntitesQuerying Entites
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];[request setSortDescriptors:sortDescriptors];
NSError *error = nil;NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];if (mutableFetchResults == nil) { // Handle the error.}
Querying EntitesQuerying Entites
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];[request setSortDescriptors:sortDescriptors];
NSError *error = nil;NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];if (mutableFetchResults == nil) { // Handle the error.}
PredicatesPredicates
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(lastName like[cd] %@) AND (birthday > %@)", lastNameSearchString, birthdaySearchDate];
NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"anAttribute == YES"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"grade > %d", 7];
[fetchRequest setPredicate:predicate];
Inserting EntitiesInserting Entities
Insert into managed object contextInsert into managed object context
Entities are not yet persisted until context is Entities are not yet persisted until context is savedsaved
Inserting EntitiesInserting 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. }}
Inserting EntitiesInserting 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. }}
Inserting EntitiesInserting 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. }}
Inserting EntitiesInserting 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. }}
Deleting EntitesDeleting Entites
Entities are marked as deletedEntities are marked as deleted
No longer returned in queriesNo longer returned in queries
Not actually deleted until context is savedNot actually deleted until context is saved
Deletes can be discarded before save by Deletes can be discarded before save by discarding or resetting the contextdiscarding or resetting the context
Deleting EntitesDeleting 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. }}
Updating EntitiesUpdating Entities
Same as insertSame as insert
Change properties and save contextChange properties and save context
Updates can be discarded before save by Updates can be discarded before save by discarding or resetting the contextdiscarding or resetting the context
MigrationsMigrations
Schemas changeSchemas change
Create new model version Create new model version
Automatic lightweight migrationAutomatic lightweight migration
Manual migrationManual migration
Not all changes require migrationNot all changes require migration
Validation, default values, Objective-C classValidation, default values, Objective-C class
Concurency TypesConcurency Types
iOS 5 >=iOS 5 >=
NSConfinementConcurrencyTypeNSConfinementConcurrencyType
Pre iOS 5 ConcurrencyPre iOS 5 Concurrency
NSPrivateQueueConcurrencyType NSPrivateQueueConcurrencyType
Private dispatch queuePrivate dispatch queue
NSMainQueueConcurrencyType NSMainQueueConcurrencyType
Main QueueMain Queue
ResourcesResources
Core Data Programming Guide Core Data Programming Guide http://developer.apple.com/library/mac/#http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.htmldocumentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html
Predicate Programming Guide Predicate Programming Guide http://developer.apple.com/library/mac/#http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/predicates.htmldocumentation/Cocoa/Conceptual/Predicates/predicates.html
Grand Central Dispatch (GCD)Grand Central Dispatch (GCD)http://developer.apple.com/library/ios/#http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Referencedocumentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html/reference.html
ResourcesResources
Magical RecordMagical Recordhttp://developer.apple.com/library/mac/#http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.htmldocumentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html
Multi-Context Core DataMulti-Context Core Datahttp://www.cocoanetics.com/2012/07/multi-context-coredata/http://www.cocoanetics.com/2012/07/multi-context-coredata/
Core Data EditorCore Data Editorhttp://christian-kienle.de/CoreDataEditorhttp://christian-kienle.de/CoreDataEditor
Q&AQ&A